Compare commits

..
2 Commits
Author SHA1 Message Date
av 95fed623e7 обслуживание: найденная дельта останавливает работу предложением, а не отказом
Стоп по найденной дельта-спеке говорил только «поведение меняется, дальше идёт
решение». Классификация при этом падала на человека в момент, когда весь
материал для неё у исполнителя, а задача выглядела сломанной, хотя она просто
оказалась шире своего типа.

Порядок теперь из трёх шагов: назвать тип, которым задача оказалась (fix —
расходится с заявленным, feature — снаружи появляется то, чего не было),
объяснить простым языком, что нашлось, и дать два решения — переформулировать
запись и решать процессом того типа следующим прогоном либо прекратить работу.
Третьего решения, «доделать как обслуживание», нет.

Тип исполнитель предлагает, меняет его av-dev-tasks:tasks и только после ответа:
переклеенный на ходу тип назначает себе другой процесс и другую глубину проверки.
Сделанное при любом решении остаётся в рабочем дереве незакоммиченным.
2026-08-13 09:30:52 +03:00
av 42849c13eb resolve: третий сценарий — обслуживание, у цикла SDD там нет входа
Задача, не меняющая поведения (тулчейн, зависимости, сборка, гит-хуки, перенос,
чистка), шла полным циклом решения. Все его шаги стоят на дельта-спеках, а у
chore их нет по построению: цикл не урезан ради дешевизны, он остаётся без входа.

Признак — связка: тип записи предлагает, отсутствие дельт подтверждает, а
расхождение признаков это стоп. Размер признаком не стал намеренно: «мелкое —
коротким путём» и есть самая дешёвая лазейка. Планового стопа у сценария нет
вовсе — объяснять человеку нечего, выбора там не делают; правило необратимого
поэтому действует жёстче, чем в двух других.

Ревью идёт фиксированным планом без метки и без разметчика — autotests и
operations, плюс conventions с техническим разбором, когда дифф трогает код.
Конвейер получил раздел «Прогон без change»: он написан вокруг change, и без
этой строки вызов упирался бы в предпосылку OpenSpec. Главный шаг сценария —
синк документации, а триггеры ADR работают стоп-признаком: своего источника у
обслуживания нет, и решение с ценой уходит в разведку.
2026-08-13 09:22:50 +03:00
10 changed files with 677 additions and 47 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
{ {
"name": "av-dev-code", "name": "av-dev-code",
"source": "./av-dev-code", "source": "./av-dev-code",
"description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария два, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой." "description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария три, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Сценарий обслуживания (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) change не заводит и планового стопа не имеет: спека там не меняется по построению, поэтому цикл SDD остаётся без входа, а ревью идёт фиксированным планом без метки. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой."
}, },
{ {
"name": "av-dev-git", "name": "av-dev-git",
+99
View File
@@ -3820,3 +3820,102 @@ change по нему не будет никогда, — и такое реше
211. **Шаг, собирающий пачку, стоит после последнего, кто в неё кладёт.** Вычитка 211. **Шаг, собирающий пачку, стоит после последнего, кто в неё кладёт.** Вычитка
на шаге записи проверила бы половину написанного, а после коммита — уже на шаге записи проверила бы половину написанного, а после коммита — уже
историю. историю.
## 63. Обслуживание — третий сценарий: у цикла SDD там нет входа (2026-08-13)
Задача, не меняющая поведения — тулчейн и сборка, зависимости, гит-хуки, перенос,
чистка, — шла полным циклом решения: `propose`, разметка, ревью дизайна,
чекпоинт, `archive`. Все пять шагов стоят на дельта-спеках, а у типа `chore`
дельта-спек **нет по построению**: тип определён через «наблюдаемое поведение не
меняется». Цикл не урезается ради дешевизны — он остаётся без входа, и change,
заведённый под такую задачу, пуст, а разметчик по нему называет не те темы.
**Признак сценария — связка из двух проверок, и обе обязательны.** Тип записи
предлагает (`chore`, реже `fix`, чьё исправление возвращает поведение к уже
записанному), отсутствие дельт подтверждает. Тип объявляет автор и может
ошибиться; отсутствие дельт — суждение исполнителя, и в одиночку оно
самообслуживающееся. Разошлись — стоп, а не выбор.
**Размер признаком не стал намеренно.** «Мелкая задача — короткий путь» это
универсальная лазейка: скилл сам называет занижение метки и обход чекпоинта самым
дешёвым способом «ускориться». Однострочная правка, меняющая поведение, идёт
полным циклом; крупная чистка, не меняющая, — обслуживанием.
**Планового стопа у сценария нет вовсе.** Чекпоинт объясняет человеку выбор, а
выбора здесь нет: что делать, сказано в записи, критерии приёмки дешёвые и
проверяются командой. Объяснение свелось бы к пересказу задачи её же автору.
Правило необратимого при этом действует полностью и срабатывает чаще, чем в двух
других сценариях: выкладка, токены, хуки и чужие данные — обычное содержимое
задач обслуживания.
**Ревью идёт фиксированным планом, а разметчик не зовётся.** Обе его оси не
определены: размер он выводит из артефактов change, сложность — из формы решения,
а незнакомая форма ушла в разведку ещё на первом шаге. План — `autotests`
(запуск гейта) и `operations` (сверка), плюс `conventions` с техническим разбором,
когда дифф трогает код, а не только оснастку: `review-code` — единственный проход,
который вообще говорит «здесь ошибка в логике», и чистка без него проверена лишь
на то, что она собирается. `requirements` и `security` не смотрит никто, и это
строка границ покрытия, а не умолчание.
**Найденная дельта — не поломка задачи, а обнаружение более широкого типа.**
Стоп поэтому устроен как три шага, а не как доклад об отказе: назвать тип,
которым задача оказалась (`fix` — расходится с заявленным, `feature` — снаружи
появляется то, чего не было), объяснить человеку простым языком, что нашлось, и
дать **два** решения — переформулировать запись и решать её процессом того типа
следующим прогоном либо прекратить работу. Третьего решения, «доделать как
обслуживание», нет: оно и есть молчаливое изменение поведения. Тип при этом
исполнитель **предлагает**, а меняет `av-dev-tasks:tasks` и только после ответа
— иначе исполнитель назначает себе другой процесс и другую глубину проверки сам.
**Триггеры ADR у обслуживания работают стоп-признаком, а не поводом завести
запись.** Список источников ADR канон закрыл двумя — архивный `design.md` и
записка разведки, — и обслуживание не производит ни того ни другого. Значит
дорогой откат, намеренный отказ и пересмотр прежнего решения означают здесь одно:
сценарий выбран неверно, работа идёт разведкой, где решение проходит чекпоинт
вариантов и получает законный источник. Третьего источника заводить не
понадобилось.
**Синк документации — главный шаг сценария, а не остаток.** Обслуживание не
меняет поведения, значит почти всё, что оно меняет, — документация: команды, шаги
гейта, зависимости, пути, имя ветки, место механизации правила. Ровно эти факты
`doc-code-drift` и сверяет с кодом.
**Состав гейта сверяется отдельно от цвета, а чем именно — решает проект.**
Красный, ставший зелёным, виден; «проверок стало на две меньше, обе зелёные» не
виден ничем, а это единственное место конвейера, где инструмент проверяет сам
себя. Что считается составом, объявляет проект семантикой гейта в `CLAUDE.md`;
не объявил — строка доклада «сверен только цвет», а не догадка.
**Своей capability тулчейн не получает, и своего документа канона тоже.**
Граница возможностей и сопровождения проходит по тому, кто наблюдает: гейт
наблюдаем мы, а не пользователь сервиса. Всё, что попало бы в `docs/toolchain.*`,
уже расписано по домам — `CLAUDE.md` (команды, семантика гейта, запреты, пути),
`architecture.*` (зависимости, окружение, выкладка), `conventions.*`
(механизированное), `ROADMAP.md` (работы). Проекту, которому этого мало, канон
уже даёт механизм и без новой строки в раскладке: список тем открытый, и свой
документ заводит свою тему. Цена такой темы названа — она попадает в план каждого
прогона и на большинстве задач молчит.
### Что из этого следует
212. **Короткий путь оправдан отсутствием входа, а не дешевизной.** «Тут можно
проще» — начало любой деградации; «этому шагу нечего обрабатывать» —
проверяемое утверждение, и проверяется оно тем же признаком, что и переход
между сценариями.
213. **Признак, объявляемый автором, и признак, выводимый исполнителем, держат
друг друга.** Первый один — ошибается в постановке; второй один —
самообслуживающийся. Разрешать расхождение в чью-то пользу нельзя: это
стоп.
214. **Сценарий без стопа для человека требует более жёсткого правила
необратимого, а не более мягкого.** Стопа, на котором «ой» заметили бы, там
нет.
215. **Инструмент, проверяющий сам себя, проверяется по составу, а не по
исходу.** Зелёный гейт после правки гейта не значит ничего.
216. **Место для нового документа ищется не по теме, а по бездомному факту.**
Тема «тулчейн» звучит убедительно, а фактов без дома за ней не оказалось —
значит документ был бы вторым домом четырёх чужих.
217. **Работа, переросшая свой тип, останавливается предложением, а не отказом.**
«Здесь нужно менять спеки» перекладывает классификацию на человека в момент,
когда весь материал для неё у исполнителя. Стоп обязан принести названный
тип, объяснение и закрытый список решений — иначе выбор делается вслепую или
не делается вовсе, и работа доезжает до коммита не тем процессом.
+21 -8
View File
@@ -37,19 +37,31 @@
переоценивает порциями по 5–8, расставляет верх очереди с доводом на переоценивает порциями по 5–8, расставляет верх очереди с доводом на
каждое движение. каждое движение.
- **av-dev-code** — работа по задачам: разведка, решение и проверка сделанного. - **av-dev-code** — работа по задачам: разведка, решение и проверка сделанного.
Владеет `openspec/`. **Требует OpenSpec и сам его заводит** — кроме сценария Владеет `openspec/`. **Требует OpenSpec и сам его заводит** — кроме сценариев
разведки, которому он не нужен. разведки и обслуживания, которым он не нужен.
- `openspec` — завести, настроить и **проверить** `openspec/` в проекте: - `openspec` — завести, настроить и **проверить** `openspec/` в проекте:
`openspec init`, замена примера в `config.yaml` настройкой канонической `openspec init`, замена примера в `config.yaml` настройкой канонической
формы, скрипт `openspec.py` (форма файла + сверка слепка с живой версией формы, скрипт `openspec.py` (форма файла + сверка слепка с живой версией
инструмента). Каталог принадлежит конвейеру, а не канону: без конвейера он инструмента). Каталог принадлежит конвейеру, а не канону: без конвейера он
проекту не нужен, и `docs.py` о нём молчит; проекту не нужен, и `docs.py` о нём молчит;
- `resolve` — одна задача от постановки до закрытия. **Точка входа одна, а - `resolve` — одна задача от постановки до закрытия. **Точка входа одна, а
сценария два, и выбирает сценарий сам скилл, прочитав постановку:** сценария три, и выбирает сценарий сам скилл, прочитав постановку:**
классифицировать задачу до вызова человек всё равно не может — «есть ли классифицировать задачу до вызова человек всё равно не может — «есть ли
очевидный способ решения» видно после чтения записи. очевидный способ решения» и «меняется ли спека» видно после чтения записи.
**Решение** идёт циклом SDD с чекпоинтом после ревью дизайна: объяснение **Решение** идёт циклом SDD с чекпоинтом после ревью дизайна: объяснение
человеческим языком, повод скорректировать ход. человеческим языком, повод скорректировать ход.
**Обслуживание** (тип `chore`: тулчейн и сборка, зависимости, гит-хуки,
перенос, чистка) change не заводит и планового стопа не имеет вовсе: дельта-спек
у него нет **по построению**, то есть цикл SDD здесь не урезан, а остаётся без
входа. Ревью идёт фиксированным планом без метки и без разметчика — `autotests`
и `operations`, плюс `conventions` с техническим разбором, если дифф трогает
код; главный шаг сценария — синк документации, потому что обслуживание чаще
прочих двигает как раз те факты, которые сверяются с кодом. Правка гейта
сверяется по составу проверок, а не по цвету. Нашлась дельта-спека — задача
**оказалась шире своего типа**: работа останавливается, тип называется
(`fix` или `feature`), человек получает объяснение простым языком и два
решения — переформулировать запись и решать её процессом того типа следующим
прогоном либо прекратить; «доделать как обслуживание» решением не является.
**Разведка** (тип `research`, сырая идея, мутная постановка) кода не пишет **Разведка** (тип `research`, сырая идея, мутная постановка) кода не пишет
вовсе: её чекпоинт — варианты, 2–4 способа решить с ценой каждого, — стоит до вовсе: её чекпоинт — варианты, 2–4 способа решить с ценой каждого, — стоит до
первого написанного требования, а исход уезжает в документы канона и в первого написанного требования, а исход уезжает в документы канона и в
@@ -57,9 +69,10 @@
своими проходами: `doc-wording` по документам, `task-form` и `task-wording` своими проходами: `doc-wording` по документам, `task-form` и `task-wording`
по записям. Выбранный способ реализуется **следующим прогоном**, и запускает его по записям. Выбранный способ реализуется **следующим прогоном**, и запускает его
человек: смена сценария по ходу — событие с названным исходом, а не тихий человек: смена сценария по ходу — событие с названным исходом, а не тихий
поворот. Оба сценария лежат справочниками и одинаково — `references/solve.md` поворот. Все три сценария лежат справочниками и одинаково —
и `references/research.md`; в самом скилле только вход, развилка и правила, `references/solve.md`, `references/maintain.md` и `references/research.md`; в
не зависящие от сценария. OpenSpec нужен решению, разведке — нет; самом скилле только вход, развилка и правила, не зависящие от сценария.
OpenSpec нужен решению, разведке и обслуживанию — нет;
- `review` — конвейер ревью **по темам**: документ проекта либо - `review` — конвейер ревью **по темам**: документ проекта либо
заводит тему проверки, либо питает чужую тему источником, либо процессный и в заводит тему проверки, либо питает чужую тему источником, либо процессный и в
ревью не читается вовсе. Разметка идёт **один раз на задачу**, сразу после ревью не читается вовсе. Разметка идёт **один раз на задачу**, сразу после
@@ -82,7 +95,7 @@
flowchart TB flowchart TB
subgraph pipe["av-dev-code — исполнение; сценарий решения требует OpenSpec"] subgraph pipe["av-dev-code — исполнение; сценарий решения требует OpenSpec"]
direction LR direction LR
tp["resolve<br/>2 сценария: разведка и решение"] --> rp["review<br/>10 агентов-проходов"] tp["resolve<br/>3 сценария: разведка,<br/>решение, обслуживание"] --> rp["review<br/>10 агентов-проходов"]
osp["openspec<br/>заводит и проверяет openspec/"] osp["openspec<br/>заводит и проверяет openspec/"]
end end
subgraph docsp["av-dev-docs — документация, владеет docs/"] subgraph docsp["av-dev-docs — документация, владеет docs/"]
+10 -3
View File
@@ -84,14 +84,21 @@
## 4. Конвейер: что осталось после `resolve` ## 4. Конвейер: что осталось после `resolve`
Сам скилл написан (`av-dev-code:resolve`, два сценария — разведка и решение, Сам скилл написан (`av-dev-code:resolve`, три сценария — разведка, решение и
по чекпоинту у каждого), `task-batch` удалён. Осталось то, что на бумаге не обслуживание; чекпоинт есть у первых двух, у обслуживания планового стопа нет),
проверяется: `task-batch` удалён. Осталось то, что на бумаге не проверяется:
- [ ] прогнать сценарий разведки на живой задаче: он написан целиком на бумаге и - [ ] прогнать сценарий разведки на живой задаче: он написан целиком на бумаге и
не исполнялся ни разу. Самое неизвестное — выбор сценария на входе (не не исполнялся ни разу. Самое неизвестное — выбор сценария на входе (не
уедет ли всё в решение, потому что «способ вроде понятен») и объём того, уедет ли всё в решение, потому что «способ вроде понятен») и объём того,
что разведка пишет в документы что разведка пишет в документы
- [ ] прогнать сценарий обслуживания на живой задаче `chore`. Неизвестных три:
**держится ли связка признаков** (не уедет ли в обслуживание то, что меняет
поведение, и наоборот — не заведут ли пустой change по привычке); **работает
ли ревью без change** — конвейер написан вокруг него, и прогон с
фиксированным планом не запускался ни разу; **есть ли чем сверить состав
гейта** — на живых проектах семантика гейта в `CLAUDE.md` может не называть
шагов поимённо, и тогда сверка вырождается в цвет
- [ ] перемерить скилл `review` тем же вопросом, что и проект целиком: - [ ] перемерить скилл `review` тем же вопросом, что и проект целиком:
сколько из его стадий реально смотрятся глазами. Тысяча строк, и весь сколько из его стадий реально смотрятся глазами. Тысяча строк, и весь
автоматический участок между чекпоинтами держится на них автоматический участок между чекпоинтами держится на них
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "av-dev-code", "name": "av-dev-code",
"description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария два, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.", "description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария три, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Сценарий обслуживания (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) change не заводит и планового стопа не имеет: спека там не меняется по построению, поэтому цикл SDD остаётся без входа, а ревью идёт фиксированным планом без метки. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.",
"author": { "author": {
"name": "Anton Vakhrushev", "name": "Anton Vakhrushev",
"email": "anwinged@gmail.com" "email": "anwinged@gmail.com"
+99 -32
View File
@@ -1,6 +1,6 @@
--- ---
name: resolve name: resolve
description: "Взять одну задачу и довести её до закрытия. Одна точка входа, два сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ решения известен — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions, если тронут код) → синк документации → коммит → закрытие; планового стопа нет, change не заводится. Нашлась дельта-спека — задача оказалась шире своего типа: стоп с объяснением простым языком и двумя решениями человека, переформулировать запись в fix или feature и решать её процессом того типа следующим прогоном либо прекратить работу. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога."
--- ---
# Работа над одной задачей # Работа над одной задачей
@@ -8,22 +8,25 @@ description: "Взять одну задачу и довести её до за
Проводит **одну** задачу от постановки до закрытия. Вокруг планового стопа — без Проводит **одну** задачу от постановки до закрытия. Вокруг планового стопа — без
согласований: механику не обсуждаем, делаем. согласований: механику не обсуждаем, делаем.
**Сценария два, а точка входа одна.** Какой из них идёт, решает **скилл**, **Сценария три, а точка входа одна.** Какой из них идёт, решает **скилл**,
прочитав постановку, а не человек до вызова: «есть ли у задачи очевидный способ прочитав постановку, а не человек до вызова: «есть ли у задачи очевидный способ
решения» видно после чтения записи, и требовать этого суждения от вызывающего решения» и «меняется ли то, что записано в спеке» видно после чтения записи, и
значит требовать его раньше, чем оно возможно. требовать этих суждений от вызывающего значит требовать их раньше, чем они
возможны.
| Сценарий | Когда | Чем кончается | | Сценарий | Когда | Чем кончается |
| --- | --- | --- | | --- | --- | --- |
| **решение** | способ известен, спорно только как | код, ревью, архив, коммит, закрытие | | **решение** | способ известен, меняется поведение | код, ревью, архив, коммит, закрытие |
| **обслуживание** | способ известен, спека не меняется: тип `chore` | правка, ревью, синк, коммит, закрытие |
| **разведка** | способа нет: тип `research`, сырая идея, мутная постановка | ответ в документах, задачи, коммит, закрытие | | **разведка** | способа нет: тип `research`, сырая идея, мутная постановка | ответ в документах, задачи, коммит, закрытие |
Ход каждого сценария живёт своим справочником: **решение** Ход каждого сценария живёт своим справочником: **решение**
[references/solve.md](references/solve.md), **разведка** [references/solve.md](references/solve.md), **обслуживание**
[references/maintain.md](references/maintain.md), **разведка**
[references/research.md](references/research.md). Здесь только общее: вход, [references/research.md](references/research.md). Здесь только общее: вход,
развилка, правила, которые не зависят от сценария. Сценарии лежат порознь и развилка, правила, которые не зависят от сценария. Сценарии лежат порознь и
одинаково, потому что привилегированного среди них нет: тот, что жил бы прямо одинаково, потому что привилегированного среди них нет: тот, что жил бы прямо
здесь, читался бы как основной, а второй — как оговорка. здесь, читался бы как основной, а прочие — как оговорка.
## Предпосылки ## Предпосылки
@@ -35,8 +38,9 @@ description: "Взять одну задачу и довести её до за
не не
пишется, сказано в `av-dev-code:review`, раздел «Предпосылки», и дом у этого пишется, сказано в `av-dev-code:review`, раздел «Предпосылки», и дом у этого
довода там. Заводить руками не надо: каталог и настройку в `config.yaml` довода там. Заводить руками не надо: каталог и настройку в `config.yaml`
делает скилл `av-dev-code:openspec`. **Сценарию разведки OpenSpec не нужен** делает скилл `av-dev-code:openspec`. **Сценариям разведки и обслуживания
она не заводит change; `opsx:explore` берётся, если плагин есть. OpenSpec не нужен** — они не заводят change; `opsx:explore` берётся разведкой,
если плагин есть.
- **Проектные копии этих скиллов и агентов удаляются при установке плагина** - **Проектные копии этих скиллов и агентов удаляются при установке плагина**
(`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого (`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого
поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом
@@ -116,18 +120,37 @@ description: "Взять одну задачу и довести её до за
## Развилка: какой сценарий ## Развилка: какой сценарий
Она одна, и стоит до всякой работы: **есть ли у задачи один очевидный способ Она в два вопроса, и оба стоят до всякой работы.
решения?**
**Первый: есть ли у задачи один очевидный способ решения?**
- **есть** — что делать, понятно; спорно только как. **Сценарий решения**
[references/solve.md](references/solve.md);
- **нет** — тип `research`, сырая идея, новое и незнакомое, мутная постановка, - **нет** — тип `research`, сырая идея, новое и незнакомое, мутная постановка,
два подхода с разной ценой. **Сценарий разведки** два подхода с разной ценой. **Сценарий разведки**
[references/research.md](references/research.md). [references/research.md](references/research.md);
- **есть** — что делать, понятно; спорно только как. Тогда второй вопрос.
Признак не в объёме работы. Крупная задача с очевидным способом идёт в решение; **Второй: меняется ли то, что записано в `openspec/specs/`?**
маленькая, но незнакомая — в разведку. Тип `research` в разведку идёт всегда: её
исход знание, а не изменение системы. - **меняется** — появляется или правится поведение. **Сценарий решения**
[references/solve.md](references/solve.md);
- **не меняется** — тулчейн и сборка, зависимости, гит-хуки и шаги гейта,
перенос, чистка. **Сценарий обслуживания**
[references/maintain.md](references/maintain.md).
**Второй вопрос решается связкой из двух признаков, и оба обязательны:** тип
записи предлагает (`chore`, реже `fix`, возвращающий поведение к уже
записанному), а отсутствие дельт подтверждает. Тип объявляет автор и может
ошибиться; отсутствие дельт — твоё суждение и принимается только вместе с типом.
Признаки разошлись — это стоп, а не выбор: скажи, что тип и предмет работы не
сходятся, и остановись. Подробно — [maintain.md](references/maintain.md), раздел
«Признак — связка, а не одно условие».
**Признак не в объёме работы, и это относится к обоим вопросам.** Крупная задача
с очевидным способом идёт в решение; маленькая, но незнакомая — в разведку;
однострочная правка, меняющая поведение, идёт полным циклом решения, а не
обслуживанием. Путь, выбираемый по самооценке размера, — самый дешёвый способ
«ускориться» и самый дорогой по последствиям. Тип `research` в разведку идёт
всегда: её исход знание, а не изменение системы.
**Назови выбранный сценарий вслух первой репликой** — одной строкой, с причиной. **Назови выбранный сценарий вслух первой репликой** — одной строкой, с причиной.
Молча выбранный сценарий человек обнаруживает по тому, что работа пошла не туда, Молча выбранный сценарий человек обнаруживает по тому, что работа пошла не туда,
@@ -135,15 +158,33 @@ description: "Взять одну задачу и довести её до за
### Сценарий выбирается один раз ### Сценарий выбирается один раз
**Смена сценария по ходу — событие, а не тихий поворот**, и каждая из двух смен **Смена сценария по ходу — событие, а не тихий поворот**, и каждая смена
устроена по-своему: устроена по-своему:
- **решение → разведка**: обнаружилось, что очевидного способа нет. Это **стоп** - **решение → разведка**: обнаружилось, что очевидного способа нет. Это **стоп**
с исходом «нужна разведка»: назови, что именно неясно, и не продолжай. с исходом «нужна разведка»: назови, что именно неясно, и не продолжай.
Кода к этому моменту не написано, и писать его «пока разбираемся» нельзя; Кода к этому моменту не написано, и писать его «пока разбираемся» нельзя;
- **разведка → решение**: способ выбран на чекпоинте вариантов. Разведка **всё - **обслуживание → решение**: нашлась дельта-спека, то есть поведение всё-таки
равно доводится до конца** — ответ записан, задачи уточнены, коммит сделан, — меняется. Задача не сломалась — она **оказалась шире своего типа**, и стоп
и решение идёт **следующим прогоном**, который запускает человек. здесь несёт человеку выбор: назови тип, которым она оказалась (`fix`
расходится с заявленным, `feature` — снаружи появляется то, чего не было),
объясни простым языком, что нашлось, и дай два решения — **переформулировать
запись и решать процессом того типа следующим прогоном** либо **прекратить
работу**. Третьего — «доделать как обслуживание» — нет. Исход в обоих случаях
«меняется спека»; сделанное остаётся в рабочем дереве незакоммиченным, тип
меняет `av-dev-tasks:tasks` и только после ответа. Подробно —
[maintain.md](references/maintain.md), раздел «Дельта нашлась по ходу»;
- **обслуживание → разведка**: форма правки неизвестна (мажорное обновление,
смена сборщика). **Стоп** с исходом «нужна разведка», по тому же основанию,
что и у решения;
- **разведка → решение или обслуживание**: способ выбран на чекпоинте вариантов.
Разведка **всё равно доводится до конца** — ответ записан, задачи уточнены,
коммит сделан, — и работа идёт **следующим прогоном**, который запускает
человек.
Обратной смены «решение → обслуживание» нет: задача, заведшая change, доводится
циклом решения. Дельта-спеки, оказавшиеся пустыми, — находка ревью дизайна о
самой постановке, а не повод свернуть на короткий путь из середины длинного.
**Соблазн «разведаю по ходу» живёт именно здесь**, и он дорог тем, что выглядит **Соблазн «разведаю по ходу» живёт именно здесь**, и он дорог тем, что выглядит
экономией одного прогона. Разведка внутри решения не имеет своего чекпоинта: экономией одного прогона. Разведка внутри решения не имеет своего чекпоинта:
@@ -156,13 +197,19 @@ flowchart TD
in["вход: файл, слаг или текст"] in["вход: файл, слаг или текст"]
ready["ready: готовность записи<br/>av-dev-tasks:tasks"] ready["ready: готовность записи<br/>av-dev-tasks:tasks"]
fork{"есть очевидный<br/>способ решения?"} fork{"есть очевидный<br/>способ решения?"}
fork2{"меняется ли<br/>спека?"}
solve["сценарий решения<br/>references/solve.md<br/>код, ревью, архив, коммит"] solve["сценарий решения<br/>references/solve.md<br/>код, ревью, архив, коммит"]
main["сценарий обслуживания<br/>references/maintain.md<br/>правка, ревью, синк, коммит"]
res["сценарий разведки<br/>references/research.md<br/>ответ в документы и задачи"] res["сценарий разведки<br/>references/research.md<br/>ответ в документы и задачи"]
in --> ready --> fork in --> ready --> fork
fork -->|"да"| solve fork -->|"да"| fork2
fork -->|"нет"| res fork -->|"нет"| res
fork2 -->|"да"| solve
fork2 -->|"нет: тип chore"| main
solve -.->|"способа всё же нет:<br/>стоп, кода не написано"| res solve -.->|"способа всё же нет:<br/>стоп, кода не написано"| res
main -.->|"нашлась дельта: стоп,<br/>тип на fix или feature,<br/>следующим прогоном"| solve
main -.->|"форма неизвестна:<br/>стоп"| res
res -.->|"способ выбран:<br/>следующим прогоном,<br/>зовёт человек"| solve res -.->|"способ выбран:<br/>следующим прогоном,<br/>зовёт человек"| solve
``` ```
@@ -171,10 +218,21 @@ flowchart TD
## Автономность и плановый стоп ## Автономность и плановый стоп
**У каждого сценария ровно один плановый стоп**, и стоят они в разных местах: **У двух сценариев ровно один плановый стоп**, и стоят они в разных местах:
у решения — объяснение после ревью дизайна, у разведки — варианты до первого у решения — объяснение после ревью дизайна, у разведки — варианты до первого
написанного требования. Правило вокруг них общее. написанного требования. Правило вокруг них общее.
**У обслуживания планового стопа нет вовсе, и это следствие, а не поблажка.**
Один стоп с ожиданием ответа у него всё же есть — по найденной дельта-спеке, — но
плановым он не является: через него проходят только те прогоны, где задача
оказалась не тем, чем объявлена.
Чекпоинт объясняет человеку **выбор**, а у обслуживания выбора нет по
построению: что делать, сказано в записи, и объяснение свелось бы к пересказу
задачи её же автору. Стоп, на котором нечего решать, вырождается в обряд
одобрения и обесценивает те стопы, где решать есть что. Правило необратимого
(ниже) действует там полностью и срабатывает чаще, чем в двух других сценариях:
выкладка, токены, хуки и чужие данные — обычное содержимое задач обслуживания.
**Вокруг чекпоинта умолчание прежнее — делать, а не спрашивать.** Чекпоинт не **Вокруг чекпоинта умолчание прежнее — делать, а не спрашивать.** Чекпоинт не
отменяет автономность, он даёт развилкам плановое место, куда копиться. отменяет автономность, он даёт развилкам плановое место, куда копиться.
@@ -247,25 +305,30 @@ flowchart TD
ли решаем», чекпоинт разведки — «каким из способов», но не «надо ли». ли решаем», чекпоинт разведки — «каким из способов», но не «надо ли».
Что не принадлежит **отдельному сценарию**, названо у него же: урожай ревью и Что не принадлежит **отдельному сценарию**, названо у него же: урожай ревью и
выбор способа — в [solve.md](references/solve.md), код и приоритет — в выбор способа — в [solve.md](references/solve.md), изменение поведения и нарезка
пачки — в [maintain.md](references/maintain.md), код и приоритет — в
[research.md](references/research.md). [research.md](references/research.md).
## Наблюдаемые исходы ## Наблюдаемые исходы
**У каждого сценария их четыре**, и живут они у сценария: **У каждого сценария их четыре**, и живут они у сценария:
[решение](references/solve.md) — сделана, не доведена, оказалась крупнее задачи, [решение](references/solve.md) — сделана, не доведена, оказалась крупнее задачи,
нужна разведка; [разведка](references/research.md) — способ выбран, знание нужна разведка; [обслуживание](references/maintain.md) — сделана, не доведена,
записано, отказ, не доведена. меняется спека, нужна разведка; [разведка](references/research.md) — способ
выбран, знание записано, отказ, не доведена.
Общего исхода нет намеренно. «Сделана» у решения и «знание записано» у разведки — Общего исхода нет намеренно. «Сделана» у решения и «знание записано» у разведки —
разные вещи с разной приёмкой, и слово, накрывающее оба, скрывало бы именно то, разные вещи с разной приёмкой, и слово, накрывающее оба, скрывало бы именно то,
чем прогон кончился. чем прогон кончился. «Сделана» у решения и у обслуживания совпадает словом, но не
определением: у первого в него входит пройденный чекпоинт и заархивированный
change, у второго — сверенный состав гейта и синк.
## Доклад ## Доклад
Ядро общее, и в нём обязательно: Ядро общее, и в нём обязательно:
- **какой сценарий шёл** — решение или разведка, — и почему выбран он; - **какой сценарий шёл** — решение, обслуживание или разведка, — и почему выбран
он;
- **исход** одним из четырёх слов своего сценария и, если он не благополучный, - **исход** одним из четырёх слов своего сценария и, если он не благополучный,
чем ограничен результат; чем ограничен результат;
- что сделано, какие вопросы записаны и куда; - что сделано, какие вопросы записаны и куда;
@@ -273,6 +336,8 @@ flowchart TD
Сверх ядра каждый сценарий добавляет своё: [solve.md](references/solve.md) — Сверх ядра каждый сценарий добавляет своё: [solve.md](references/solve.md) —
чекпоинт, change, критерии приёмки, урожай и границы покрытия; чекпоинт, change, критерии приёмки, урожай и границы покрытия;
[maintain.md](references/maintain.md) — чем подтверждён признак, состав гейта до
и после, критерии приёмки, урожай и границы покрытия;
[research.md](references/research.md) — вопрос и ответ, адреса записи, заведённые [research.md](references/research.md) — вопрос и ответ, адреса записи, заведённые
задачи, рамки. задачи, рамки.
@@ -281,11 +346,13 @@ flowchart TD
- **Не завязывайся на основную ветку и корень репозитория.** Скилл работает в - **Не завязывайся на основную ветку и корень репозитория.** Скилл работает в
текущем worktree и на текущей ветке: не делай `git checkout`/`switch`, не текущем worktree и на текущей ветке: не делай `git checkout`/`switch`, не
создавай веток, не пушь. создавай веток, не пушь.
- Прогон проходит **один** чекпоинт, и это норма, а не упрощение. Два стопа за - Прогон проходит **не больше одного** чекпоинта, и это норма, а не упрощение.
одну задачу — цена незнания способа, и платится она двумя прогонами, а не одним Два стопа за одну задачу — цена незнания способа, и платится она двумя
длинным. прогонами, а не одним длинным. У обслуживания чекпоинта нет ни одного, и это
тоже норма: там нечего решать.
- Держи вызывающего в цикле короткими репликами на переходах фаз, но не проси - Держи вызывающего в цикле короткими репликами на переходах фаз, но не проси
подтверждать механику: чекпоинт — единственное место, где ждут ответа. подтверждать механику: чекпоинт — единственное место, где ждут ответа, а в
обслуживании такого места нет вовсе.
- **Сценарий назван вслух — значит, его можно оспорить.** Человек, увидевший в - **Сценарий назван вслух — значит, его можно оспорить.** Человек, увидевший в
первой реплике «иду разведкой, потому что способа не видно», поправит выбор первой реплике «иду разведкой, потому что способа не видно», поправит выбор
одной фразой; молча выбранный сценарий он поправит через полчаса работы. одной фразой; молча выбранный сценарий он поправит через полчаса работы.
@@ -0,0 +1,390 @@
# Сценарий «обслуживание»
Способ решения известен, а **того, что нормирует спека, задача не трогает**:
тулчейн и сборка, зависимости, гит-хуки и шаги гейта, перенос и чистка. Сценарий
**пишет код**, но не заводит change и не пишет требований. Исход — работающая
оснастка и синхронная ей документация.
Сценарий выбирается развилкой на входе скилла ([SKILL.md](../SKILL.md), раздел
«Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его
ход; общее для всех трёх сценариев — вход, обращение к соседним плагинам, правило
записанного вопроса, правило необратимого — живёт в SKILL.md и тут не
пересказывается.
## Почему цикл SDD здесь не урезан, а не имеет входа
Это не поблажка по цене, и формулировать её как «мелкая задача — короткий путь»
нельзя: путь, выбираемый по самооценке размера, и есть тот самый дешёвый способ
«ускориться», против которого написана вся защита сценария решения.
**У обслуживания нет дельта-спек по построению.** Тип `chore` определён через
«наблюдаемое поведение не меняется», а на дельтах стоит весь цикл: `propose`
их порождает, разметка выведена **из них**, `review-specs` сверяет **с ними**,
объяснение чекпоинта собирается из `proposal.md` и `design.md`, `archive` вливает
их в актуальные спеки. Change без дельт — пустой артефакт, который потом надо
архивировать, и разметчик по нему назовёт не те темы.
То есть механика цикла остаётся не пропущенной, а **без входа**. Отсюда и состав
сценария: выпали ровно те шаги, у которых нет предмета, и не выпал ни один из
тех, у которых он есть.
## Признак — связка, а не одно условие
Сценарий выбирается двумя проверками сразу, и обе обязательны:
1. **тип записи предлагает**`chore`, реже `fix`, чьё исправление возвращает
поведение к уже записанному в спеке;
2. **отсутствие дельт подтверждает** — прочитав постановку, ты не находишь
требования, которое пришлось бы добавить, изменить или снять.
Один признак без второго не выбирает сценарий. Тип объявляет автор записи, и он
может ошибиться в обе стороны; отсутствие дельт — суждение исполнителя, и оно
принимается только тогда, когда согласуется с объявленным типом. Расхождение
двух признаков — это не развилка, а стоп: скажи, что тип и предмет работы
разошлись, и остановись.
**Имя сценария не равно имени типа, и это намеренно.** `fix` без дельта-спеки
идёт сюда законно — поведение разошлось с **заявленным**, значит заявленное уже
записано, и менять спеку не нужно. Сценарий, названный именем типа, такую задачу
либо отправил бы в полный цикл ради пустого change, либо принял бы как
исключение, а исключения не исполняются.
## Дельта нашлась по ходу — стоп, и у него свой порядок
Признак тот же, что на шаге 7 сценария решения: **меняется ли то, что записано в
`openspec/specs/`**. Обнаружилось, что меняется, — работа перестала быть
обслуживанием в ту же секунду, и продолжать её нельзя: коммит обслуживания
заявляет «поведение не менялось», а оно меняется.
**Задача при этом не сломалась — она оказалась шире своего типа.** Поэтому стоп
здесь не «бросить и доложить», а три шага по порядку.
**1. Назови тип, которым задача оказалась.** Разрез тот же, по которому типы и
разведены:
- **`fix`** — поведение расходится с **заявленным**: спека уже описывает верное,
и правка возвращает систему к записанному;
- **`feature`** — снаружи появляется то, чего не было: спеке нужно новое
требование.
Тип называется прямо и с причиной. «Нужно менять спеки» без имени типа
перекладывает классификацию на человека в тот момент, когда весь материал для неё
у тебя.
**2. Объясни человеку простым языком.** Экран текста, не больше:
- **что просили сделать** — одной фразой из записи;
- **что нашлось** — какое поведение меняется, словами домена, а не именами
файлов и функций;
- **почему это перестало быть обслуживанием** — одной фразой: у обслуживания
поведение не меняется по определению;
- **чем задача становится** — `fix` или `feature`, с причиной из разреза выше;
- **что уже сделано** и что из этого лежит в рабочем дереве.
Проверка на простой язык та же, что у чекпоинтов двух других сценариев: **в
тексте нет `SHALL`, нет имён файлов и функций там, где вещь называется
по-русски, и нет слов, которых нет в паспорте проекта.**
**3. Дай два решения и жди ответа.** Их ровно два, и оба законны:
- **переформулировать запись** — тип меняется на названный, и дальше задача идёт
**процессом своего типа**: сценарием решения, следующим прогоном. Формат записи
правит `av-dev-tasks:tasks`, а не ты: у нового типа своя схема разделов, и
готовность её проверит `ready` — той же машиной, что и на входе. Прогон
обслуживания на этом кончается, исход — «меняется спека»;
- **прекратить работу** — человек не готов расширять задачу сейчас. Исход тот
же, запись остаётся как была, вопрос записывается там, где проект держит
вопросы.
**Третьего решения — «доделать как обслуживание» — нет.** Оно и есть то самое
молчаливое изменение поведения, против которого стоит весь разрез: под коммитом,
заявляющим «поменяли оснастку», уехала бы правка, не прошедшая ни ревью дизайна,
ни чекпоинта, и не оставившая следа в спеках.
**Сделанное не выбрасывается ни при каком из двух решений.** Оно остаётся в
рабочем дереве незакоммиченным: при переформулировке уезжает в change следующим
прогоном, при отказе — человек решает сам, откатить или оставить. Коммитить его
сообщением про обслуживание нельзя.
**Это единственное место сценария, где ждут ответа**, и плановым стопом оно не
становится: плановый стоп проходят все прогоны, а этот — только те, где задача
оказалась не тем, чем объявлена. Прогон, дошедший до него, стоит дороже обычного
— и это довод за проверку признака на шаге 1, а не после написанного кода.
## OpenSpec здесь не предпосылка
Как и разведке, обслуживанию OpenSpec не нужен: оно не заводит change, не пишет
дельта-спек и не архивирует. Ни один из проходов его плана ревью на дельта-спеки
не завязан — это сказано и в `av-dev-code:review`, раздел «Прогон без change».
Каталога в проекте нет — обслуживание идёт целиком, и деградацией это не
является.
## Планового стопа у этого сценария нет
**И это следствие, а не упрощение.** Чекпоинт решения объясняет человеку
**выбор**: в чём проблема, как решаем, чем рискуем. У обслуживания выбора нет по
построению — что делать, сказано в записи, а критерии приёмки у него самые
дешёвые из всех типов: команда, которая раньше падала или требовала трёх шагов.
Объяснение свелось бы к пересказу задачи её же автору. Стоп, на котором нечего
решать, вырождается в обряд одобрения и обесценивает те стопы, где решать есть
что.
**Место, где ответа всё же ждут, одно, и плановым оно не является** — стоп по
найденной дельте (раздел «Дельта нашлась по ходу»). Через него проходят не все
прогоны, а только те, где задача оказалась не тем, чем объявлена.
**Правило необратимого при этом действует полностью** (SKILL.md, «Когда
спрашивать вне чекпоинта»), и здесь оно опаснее, чем кажется. Единственный
сценарий без планового стопа — ровно тот, чья работа чаще прочих лезет в
выкладку, в токены, в хуки и в чужие данные. Правка оснастки выглядит безобидной
до момента, когда её уже не откатить.
## Ход работы
```mermaid
flowchart TD
in["сценарий выбран: обслуживание"]
s1["1. прочитать задачу<br/>критерии приёмки и границы"]
s2["2. сделать правку<br/>гейт тронут — сверить состав, не цвет"]
s3["3. гейт проекта до зелёного"]
s4["4. ревью фиксированным планом<br/>av-dev-code:review, без change"]
s5["5. синк документации — av-dev-docs:docs"]
s6["6. коммит работы — av-dev-git:commit"]
s7["7. закрыть задачу — av-dev-tasks:tasks,<br/>вторым коммитом учёта"]
out["исход назван"]
in --> s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> out
s1 -.->|"форма правки неизвестна"| stop1["стоп: нужна разведка"]
s2 -.->|"меняется дельта-спека"| stop2["стоп: идёт решением,<br/>следующим прогоном"]
```
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при расхождении
прав текст.
## Наблюдаемые исходы сценария
Четыре, и каждый обязан быть назван в докладе прямо:
- **сделана** — определение сделанного выполнено целиком;
- **не доведена** — с причиной и с записанным вопросом; названо, что именно
сделано и до какой границы;
- **меняется спека** — работа оказалась шире своего типа. Стоп с объяснением и
двумя решениями человека: переформулировать запись в `fix` или `feature` и
решать её процессом того типа следующим прогоном — либо прекратить. Сделанное
остаётся в рабочем дереве незакоммиченным. Доклад называет **оба**: какой тип
предложен и что человек выбрал;
- **нужна разведка** — форма правки неизвестна (мажорное обновление, смена
сборщика, переезд гейта на другой инструмент) **или сработал триггер ADR**:
дорогой откат, намеренный отказ от очевидного подхода, пересмотр прежнего
решения. Стоп с названной причиной, разведка идёт следующим прогоном.
**Последний исход — не редкость, и его стоит ждать.** Незнакомое обслуживание это
выбор подхода с ценой и с тем, что становится невозможным, — предмет чекпоинта
вариантов, а не работы без стопа. И там же решение получает законный источник для
ADR: список источников канон закрыл двумя — архивный `design.md` и записка
разведки, — а обслуживание не производит ни того ни другого.
## Определение сделанного
Задача сделана, когда верно всё:
1. гейт проекта зелёный, и **если правка трогала сам гейт — сверен его состав**,
а не только цвет;
2. ревью проведено фиксированным планом сценария, исход назван по каждой теме
плана, а темы, которых в плане нет, названы в границах покрытия;
3. **документация синхронизирована с принуждённым отрицанием** — каждый документ
канона получил строку;
4. коммит сделан в текущую ветку;
5. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван
оракул и наблюдаемый исход.** Это доклад приёмщику, а не отметка «принято»:
исполнитель и приёмщик здесь совпали, и правило то же, что в решении.
## Шаги
### 1. Прочитать задачу
Прочитай запись. У `chore` обязательны два раздела, и оба нужны тебе прямо
сейчас: **«Затрагивает»** — границы, которые у обслуживания часто не в коде
(конфиг и его образцы, версия зависимости, команда сборки, файл CI), и
**«Критерии приёмки»** — с оракулами.
Здесь же обе проверки признака: тип предлагает, отсутствие дельт подтверждает
(раздел «Признак — связка»). И здесь же — проверка на незнакомое: если форма
правки не известна до начала, а нащупывается по ходу, объявляй исход **нужна
разведка** и не начинай.
**Проверка на «заодно».** Обслуживание любит склеиваться в пачку — обновить
зависимости, переписать сборку и убрать мёртвый код одной задачей. Не мерджится
порознь — это несколько задач: объявляй исход **не доведена** с причиной «задача
не одна» и останавливайся. Нарезкой владеет `av-dev-tasks:tasks`, а не ты, и
делать её по ходу нельзя — получится один коммит, в котором обновление
зависимости не отделить от чистки.
### 2. Сделать правку
Код и конфиги — по конвенциям проекта. Правка right-size: чинится названное в
записи, а соседнее не золотится по пути.
**Гейт правится — сверь состав, а не цвет.** Красный, ставший зелёным, виден
сразу; «проверок стало на две меньше, обе зелёные» не видно ничем, а это самая
дорогая из возможных правок оснастки: молча выключено то, чем проверяется всё
остальное. Состав проверок и способ его снять — **дело проекта**: он объявляет
их семантикой гейта в `CLAUDE.md`. Снимай исходное состояние **до** правки, по
тому, как проект это описал.
**Проект состав не описал — скажи строкой доклада, что сверен только цвет.**
Обходного пути не выдумывай: угаданный состав хуже отсутствующего, потому что
читается как сверенный. Это же строка и повод — предложить проекту дописать слот
в `CLAUDE.md`.
### 3. Гейт до зелёного
Прогони гейт и добейся зелёного — он же условие следующего шага: пока гейт
красный, опиниативные проходы не запускаются.
**Поведенческая верификация здесь другая, чем в решении.** Проверяется не новое
поведение, а то, что прежнее не поехало: команда из `CLAUDE.md` поднимается, шаг
сборки отрабатывает, хук ставится на чистом клоне. Правка, которую нельзя
проверить ничем, кроме «у меня локально работает», называется в докладе строкой.
### 4. Ревью — план фиксирован сценарием
Вызови Skill **`av-dev-code:review`**, дав базу диффа, режим и **план сценария**.
Change ты не передаёшь — его нет.
**Разметчик здесь не зовётся, и это правило, а не пропуск.** Обе оси, по которым
он судит, у обслуживания не определены: размер он меряет по `proposal.md`,
`design.md`, `tasks.md` и дельта-спекам, а незнакомость — по форме решения,
которой здесь нет (незнакомое ушло в разведку шагом 1). Разметчик без своего
корпуса вернул бы метку, выведенную из ничего.
Поэтому план у сценария **свой и постоянный**:
| Тема | Дом | Кто закрывает | Когда |
| --- | --- | --- | --- |
| `autotests` | `CLAUDE.md`, семантика гейта | `review-autotests` | всегда |
| `operations` | `architecture.*`, раздел эксплуатации | `review-basics`, глубина «сверка» | всегда |
| `conventions` + технический разбор | `conventions.*` | `review-code` | дифф трогает код, а не только оснастку |
Триаж обязателен, как и на всяком прогоне: он единственный сток и единственный,
кто сверяет план с исходом. План на его входе — не формальность: тема,
оставшаяся без отчёта, видна только ему.
**Условие третьей строки проверяемое, и смотрится оно по диффу**, а не по
намерению: обновление зависимости или правка файла CI кода не трогают, чистка и
перенос — трогают. `review-code` — единственный проход, который вообще говорит
«здесь ошибка в логике», и чистка, прошедшая без него, проверена только на то,
что она собирается.
**Границы покрытия называются полностью.** Темы `requirements` и `security` в
плане нет: у первой нет предмета — дельта-спек не существует, у второй нет
проходчика на этом сценарии. Обе уезжают в доклад строкой. Отчёт, из которого
исчезло «что не смотрел никто», сообщает «проверено», не сообщая, что именно.
Отработка — как в решении: помеченное `инлайн` чини сам и не логируй, `развилка`
— вопросом в запись. После правок снова гейт. Отложенные находки собери в секцию
доклада `Урожай`; задачи из него заводит `av-dev-tasks:tasks`, не ты.
### 5. Синк документации — главный шаг этого сценария
**Вызови Skill `av-dev-docs:docs`.** Правило то же и такое же жёсткое:
**принуждённое отрицание** — каждый документ канона либо назван обновлённым, либо
получает «не требуется, потому что…». Нетронутые группируются одной строкой.
**Здесь этот шаг весит больше, чем в решении, и вот почему.** Обслуживание не
меняет поведения — значит, почти всё, что оно меняет, это документация: команды,
шаги гейта, зависимости поимённо, пути, имя основной ветки, настройки с числовым
значением, место механизации правила. Ровно эти факты `doc-code-drift` и сверяет
с кодом (перечень закрыт, живёт в каноне) — то есть сценарий, чаще всех прочих
двигающий сверяемые факты, обязан отчитаться по ним раньше всех прочих.
Отдельно один документ, которого нет в перечне тем, а синку он нужен:
**`conventions.*`, раздел «Механизировано»** — если правило переехало в линтер, и
тогда его проза из конвенций **удаляется**, а не остаётся вторым домом.
**`adr/` этот сценарий не пополняет, и это не пропуск.** У ADR закрытый список
источников — архивный `design.md` либо записка разведки, — и ни того ни другого
обслуживание не производит. Поэтому триггеры ADR здесь работают **стоп-признаком,
а не поводом завести запись**: сработал дорогой откат, намеренный отказ от
очевидного подхода или пересмотр прежнего решения — сценарий выбран неверно,
объявляй исход **нужна разведка** и останавливайся. Решение с ценой обязано
пройти чекпоинт вариантов, а не появиться в коммите обслуживания, чей смысл —
«ничего не решали, поменяли оснастку».
Список документов и их триггеров здесь не дублируется — он в чек-листе скилла
`av-dev-docs:docs`; копия уже однажды разошлась с оригиналом. Плагина в проекте
нет — иди за перечнем в свой reference,
[references/project-facts.md](../../review/references/project-facts.md) конвейера
ревью, добавь `adr/` руками и скажи строкой, что синк сделан по перечню
документов, без списка триггеров.
### 6. Коммит
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
создавай и не переключай, ничего не пушь.
Сообщение — по-русски, **скиллом `av-dev-git:commit`**. Вызов не разрешился —
напиши сам и скажи строкой, что форму коммита не сверял никто. Одна задача — один
осмысленный коммит.
### 7. Закрыть задачу — после коммита, не раньше
**Вызови Skill `av-dev-tasks:tasks`** и попроси закрыть задачу как реализованную.
Порядок обязателен: закрытие удаляет файл задачи, и сделанное до коммита оно
оставило бы задачу закрытой без следа работы, если шаг 6 упадёт.
**Закрытие тоже коммитится — вторым коммитом, тут же**, сообщением про учёт:
`закрыта задача <slug>`. Плагина нет — ничего не выдумывай: скажи, что учёт
остаётся за владельцем, и назови исход.
## Границы: чего обслуживание не делает
- **Не меняет поведения.** Обнаружилось, что меняет, — стоп с исходом «меняется
спека»: назвать тип, объяснить, дать два решения. Это единственная граница
сценария, у которой есть проверяемый признак, и она же единственная, которую
выгодно нарушить молча.
- **Не переписывает запись задачи сам.** Тип ты **предлагаешь** с причиной,
меняет его `av-dev-tasks:tasks` и только после ответа человека: исполнитель,
переклеивший тип на ходу, назначает себе другой процесс и другую глубину
проверки.
- **Не решает, нужна ли работа.** Как и оба соседних сценария: «надо ли» —
вопрос человека.
- **Не нарезает пачку на задачи.** «Обновить зависимости и переписать сборку» —
это `av-dev-tasks:tasks` и его правила нарезки.
- **Не выбирает форму правки, когда она незнакома, и не принимает решений с
ценой.** Мажорное обновление, смена инструмента, намеренный отказ идут
разведкой: там есть чекпоинт вариантов и законный источник для ADR, здесь нет
ни того ни другого.
- **Не заводит задачи из урожая ревью.** Урожай передаётся списком.
## Доклад обслуживания
Общее ядро доклада — в SKILL.md; сверх него сценарий обязан назвать:
- **что подтвердило признак** — тип записи и то, что дельта-спек не нашлось;
дельта нашлась — **какой тип предложен, с причиной, и что человек выбрал**:
переформулировать или прекратить;
- **что стало иначе для разработчика** — одной фразой, адресуясь ему, а не
выдуманному пользователю;
- **состав гейта до и после**, если правка его трогала; не сверялся — почему;
- по каждому критерию приёмки: **оракул и наблюдаемый исход**;
- **`Урожай`** — отложенные находки списком;
- **строка границ покрытия**: план сценария фиксирован, `requirements` и
`security` на этом прогоне не смотрел никто, и разметчик не запускался.
## Тонкости сценария
- **Самый частый способ соврать этим сценарием — назвать `chore` то, что меняет
поведение.** Тип, оставшийся от первой формулировки, врёт ровно там, где по
нему выбирают путь; проверка признака стоит одного чтения записи и делается на
шаге 1, а не после написанного кода.
- **Отсутствие чекпоинта не делает сценарий автономнее прочих.** Правило
необратимого здесь то же, и срабатывает оно чаще: выкладка, токены, хуки,
чужие данные — обычное содержимое задач обслуживания.
- **Зелёный гейт после правки гейта ничего не доказывает.** Это единственное
место конвейера, где инструмент проверяет сам себя, и потому состав сверяется
отдельно от цвета.
- **Правка оснастки, сделанная «заодно» внутри чужой задачи, этим сценарием не
проходит вовсе** — она едет в чужом коммите и не получает ни своего ревью, ни
своей строки синка. Заметил нужную правку по ходу решения — вопрос в запись,
а не правка мимоходом.
+38 -1
View File
@@ -1,6 +1,6 @@
--- ---
name: review name: review
description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после propose: агент review-scope выводит размер и сложность, из их максимума — метка, и раздаёт темы проходам обеих стадий. Метка правит и ревью дизайна (small — только specs; medium — плюс rubric; large — плюс architecture), и ревью кода (small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе). Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона av-dev-docs. Вызывается из скилла resolve — двумя стадиями: ревью дизайна до кода и ревью кода после apply." description: "Конвейер ревью изменения, устроенный по темам: документ проекта либо заводит тему ревью, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Ядро тем — requirements, autotests, conventions, architecture, security, operations; список тем открытый, свои темы проект заводит документом. Разметка задачи идёт один раз, после propose: агент review-scope выводит размер и сложность, из их максимума — метка, и раздаёт темы проходам обеих стадий. Метка правит и ревью дизайна (small — только specs; medium — плюс rubric; large — плюс architecture), и ревью кода (small — гейт, спеки, код, триаж; medium — плюс приёмник тем; large — плюс доказательство: враждебные постановки, эксплуатационный постмортем, архитектурный проход на широком входе). Триаж обязателен всегда. Порядок прогона — граф зависимостей: гейт открывает опиниативные проходы, проходы с пометкой «держит машину» идут цепочкой, триаж — единственный сток. Проектная специфика приходит из документов канона av-dev-docs. Вызывается из скилла resolve — двумя стадиями: ревью дизайна до кода и ревью кода после apply. Третий вызов идёт от сценария обслуживания: без change и без метки, фиксированным планом (autotests, operations, плюс conventions, если тронут код), разметчик при этом не запускается."
--- ---
# Конвейер ревью # Конвейер ревью
@@ -55,6 +55,9 @@ description: "Конвейер ревью изменения, устроенны
этим владеет скилл `av-dev-code:openspec` — он заводит каталог и заменяет этим владеет скилл `av-dev-code:openspec` — он заводит каталог и заменяет
пример в `config.yaml` настройкой. Его же зовут `av-dev-docs:init` на новом пример в `config.yaml` настройкой. Его же зовут `av-dev-docs:init` на новом
проекте и `av-dev-docs:canon` в режиме `adopt` — на переводимом. проекте и `av-dev-docs:canon` в режиме `adopt` — на переводимом.
**Предпосылка эта — про изменение поведения, а не про всякий прогон:**
сценарий обслуживания зовёт конвейер без change и без дельта-спек, и ни один
проход его плана на них не завязан. См. «Прогон без change».
- **Документы канона** — см. следующий раздел. - **Документы канона** — см. следующий раздел.
- **Проектные копии этих скиллов и агентов удаляются при установке.** Если в - **Проектные копии этих скиллов и агентов удаляются при установке.** Если в
проекте уже лежат свои `.claude/skills/review`, проекте уже лежат свои `.claude/skills/review`,
@@ -638,6 +641,40 @@ flowchart TD
постфактум, и это единственный сигнал — ровно как и для всякой другой ошибки постфактум, и это единственный сигнал — ровно как и для всякой другой ошибки
выбора метки. выбора метки.
## Прогон без change — сценарий обслуживания
Третий вызывающий конвейера — сценарий обслуживания скилла `av-dev-code:resolve`
(тулчейн и сборка, зависимости, гит-хуки, перенос, чистка). Он приходит **без
change**: у работы, не меняющей поведения, дельта-спек нет по построению.
**Метка на таком прогоне не назначается, и разметчик не зовётся.** Обе его оси
здесь не определены: размер он выводит из `proposal.md`, `design.md`, `tasks.md`
и дельта-спек, а сложность — из формы решения, которая у обслуживания либо
известна заранее, либо задача туда не попала (незнакомое уходит в разведку).
Разметчик без своего корпуса вернул бы величину, выведенную из ничего, — и это
хуже отсутствующей метки, потому что выглядит измеренным.
**План приходит вызовом и фиксирован сценарием**, а не выводится здесь:
| Тема | Кто закрывает | Когда |
|---|---|---|
| `autotests` | `review-autotests` | всегда |
| `operations` | `review-basics`, глубина «сверка» | всегда |
| `conventions` + технический разбор | `review-code` | дифф трогает код, а не только оснастку |
Триаж обязателен и здесь — он единственный сток и единственный, кто сверяет план
с исходом. Темы `requirements` и `security` в плане отсутствуют: у первой нет
предмета, у второй нет проходчика на этом сценарии, — и обе обязаны быть названы
в границах покрытия. Дом плана — сценарий, а не этот скилл:
`av-dev-code:resolve`, `references/maintain.md`, раздел «Ревью — план фиксирован
сценарием».
**Правило гейта на таком прогоне работает жёстче обычного.** Правка, которая
трогает сам гейт, проверяется гейтом же — инструмент проверяет себя, — поэтому
сверяется не только цвет, но и состав шагов. Что считается составом, объявляет
проект семантикой гейта в `CLAUDE.md`; не объявил — это строка границ покрытия, а
не догадка прохода.
## Стадия 1 — Автотесты (обязательна при любой метке) ## Стадия 1 — Автотесты (обязательна при любой метке)
Агент `review-autotests`, тема `autotests`. Запускает команду гейта из семантики Агент `review-autotests`, тема `autotests`. Запускает команду гейта из семантики
+1 -1
View File
@@ -103,7 +103,7 @@ description: Вести содержимое документов канона
сочиняет заново. сочиняет заново.
**Второй законный источник — записка разведки**, и приходит он от скилла **Второй законный источник — записка разведки**, и приходит он от скилла
`av-dev-code:research`: решение, принятое разведкой (намеренный отказ, выбор `av-dev-code:resolve`, сценарий разведки: решение, принятое разведкой (намеренный отказ, выбор
подхода, «проверили и не делаем»), `design.md` не имеет по построению — change по подхода, «проверили и не делаем»), `design.md` не имеет по построению — change по
нему не будет никогда. Промоут при этом тот же: цитата и ссылка, но на записку. нему не будет никогда. Промоут при этом тот же: цитата и ссылка, но на записку.
Перечень источников закрыт и живёт в [каноне](../canon/references/canon.md), Перечень источников закрыт и живёт в [каноне](../canon/references/canon.md),
@@ -33,6 +33,13 @@
не `chore`. Тип, оставшийся от первой формулировки, врёт ровно там, где по нему не `chore`. Тип, оставшийся от первой формулировки, врёт ровно там, где по нему
отбирают. отбирают.
**Обнаружилось это уже в работе — запись переформулируется, а не дорешивается.**
Исполнитель останавливается, называет тип, которым задача оказалась (`fix`
поведение расходится с заявленным, `feature` — снаружи появляется то, чего не
было), и человек решает: сменить тип и решать процессом того типа — либо
прекратить. Тип меняет этот скилл, а не исполнитель по ходу: у нового типа своя
схема разделов, и `ready` проверит её заново.
## Алгоритм ## Алгоритм
1. **Проверить, что поведение не меняется.** Меняется — это `feature` или `fix`, 1. **Проверить, что поведение не меняется.** Меняется — это `feature` или `fix`,
@@ -52,6 +59,16 @@
Работа по сопровождению проекта при этом видна в роадмапе — секцией Работа по сопровождению проекта при этом видна в роадмапе — секцией
`Сопровождение`, но целью не становится. `Сопровождение`, но целью не становится.
## Кто такую задачу решает
Решает её конвейер проекта — в плагине `av-dev-code` это скилл `resolve`,
**сценарий обслуживания**: он не заводит change и не пишет требований, потому что
у работы, не меняющей поведения, дельта-спек нет по построению. Тип записи там
только **предлагает** сценарий, а подтверждает его отсутствие дельт: разошлись —
работа останавливается, и это тот самый случай, когда тип, оставшийся от первой
формулировки, врёт. Плагина нет — задача решается как проект привык, а этот скилл
её только заводит и закрывает.
## Что видит машина, а что человек ## Что видит машина, а что человек
`ready` смотрит на **наличие непустого** `Затрагивает` и на `ready` смотрит на **наличие непустого** `Затрагивает` и на