resolve: два сценария вместо одной цепочки — разведка и решение

Разведка была прологом к коду: три шага, чекпоинт вариантов — и вливание в
общую ветку. Своего исхода у неё не было, поэтому и писать в документы проекта
ей было незачем: ответ оседал в design.md будущего change.

- у разведки появился исход: ответ уезжает в документы канона, задачи заводятся
  и уточняются, написанное коммитится, запись закрывается. Кода сценарий не
  пишет вовсе, OpenSpec ему не нужен
- точка входа осталась одна, и сценарий выбирает скилл, прочитав постановку:
  «есть ли очевидный способ решения» видно после чтения записи, и требовать
  этого суждения от вызывающего значит требовать его раньше, чем оно возможно
- оба сценария лежат справочниками и одинаково — solve.md и research.md, — а в
  SKILL.md остались вход, развилка и правила, не зависящие от сценария.
  Асимметрия читалась бы как старшинство: сценарий в теле скилла выглядит
  основным, а в справочнике — оговоркой
- переход между сценариями — событие с названным исходом: решение, упёршееся в
  незнание способа, останавливается; разведка, выбравшая способ, доводится до
  конца, а код идёт следующим прогоном, который запускает человек
- канон 14: у ADR два законных источника. У решения, принятого разведкой,
  design.md нет по построению, и такое решение либо не попадало в adr/ вовсе,
  либо попадало сочинённым заново

Правки по своему же ревью, до коммита:

- версия 14 была неполной — разрез проверки, вход и устав doc-consistency,
  скелеты adr/README.md и template.md по-прежнему требовали ссылку на
  design.md. Агент краснел бы на законной записи; скелеты уезжают в проекты,
  поэтому запись журнала называет их поимённо
- canon.md объявлял себя двенадцатым, пережив версию 13. Литерал был третьим
  домом числа при двух исправных — убран, а не поправлен
- сценарий разведки был недостижим там, где обещал работать: ready требует у
  research оба раздела, включая «Куда ляжет ответ», а сценарий брался назначить
  адрес сам. Адрес назначает автор записи; сценарий — только когда записи нет
- разведка коммитила без гейта, хотя правит документы канона и индексы задач
- при переносе выпало предупреждение про закрытие разведки без записанного
  ответа — возвращено
This commit is contained in:
av
2026-08-11 11:36:37 +03:00
parent 863769406f
commit b8120d3271
15 changed files with 1073 additions and 526 deletions
@@ -0,0 +1,356 @@
# Сценарий «разведка»
Отвечает на вопрос задачи и записывает ответ туда, где он переживёт переписку.
Исход — **знание**: уточнённые документы и уточнённые задачи. **Кода этот
сценарий не пишет и change не заводит.**
Сценарий выбирается развилкой на входе скилла ([SKILL.md](../SKILL.md), раздел
«Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его
ход; общее для обоих сценариев — вход, обращение к соседним плагинам, правило
необратимого, доклад — живёт в SKILL.md и тут не пересказывается.
**Разведка кончается своим исходом, а не переходом к коду.** Выбранный способ
реализует сценарий решения, и запускает его **человек**, следующим прогоном по
уточнённой записи. Причина не в церемонии: разведка только что переписала
постановку, и брать её в работу тем же заходом значит решать за человека, стоит
ли делать это сейчас, — а это приоритет, и он не наш.
## OpenSpec здесь не предпосылка
**OpenSpec этому сценарию не нужен**, и это единственное место скилла, где он не
предпосылка. Разведка не заводит change и не пишет дельта-спеки: её артефакты —
документы канона и записи каталога задач. Скилл `opsx:explore` полезен и зовётся,
когда плагин в проекте есть; не разрешился — разведка идёт чтением документов,
кода и внешних источников, и это говорится строкой доклада, а не отменяет
работу.
## Кого зовёт этот сценарий
`av-dev-docs:docs` (ответ уезжает в документы канона), `av-dev-tasks:tasks`
(задачи заводятся и уточняются), `av-dev-git:commit`. Правило обращения к соседям
и ветка «вызов не разрешился» — общие, они в [SKILL.md](../SKILL.md).
**Отсутствие канона бьёт по разведке сильнее, чем по решению**, и сказать об этом
строкой мало: без документов у ответа нет дома, и знание осядет в переписке.
Назови исход и предложи `av-dev-docs:canon`; работу не останавливай, но адрес
ответа тогда выбираешь сам и говоришь об этом вслух.
## Что этот сценарий требует от входа
Вход общий у обоих сценариев (SKILL.md, раздел «Вход»); своего здесь три условия.
**Паспорт читается раньше кода.** Граница домена и «чем проект **не** является»
отсекают половину вариантов до того, как их начнут сравнивать, — а сравнение
вариантов и есть работа этого сценария.
**Сырьё — `research` без раздела «Вопрос» — не берётся.** Исход «не доведена» с
причиной «запись это сырьё»: у неё нет вопроса, а разведка без вопроса
превращается в чтение всего подряд с отчётом «интересно, но неприменимо».
Дописывать вопрос за автора не твоя работа — этим занят штурм сырья в
`av-dev-tasks:tasks`. Назови, чего не хватает, и остановись.
**Разведка пришла текстом — сформулируй вопрос сам одной фразой и покажи
формулировку в первой же реплике.** Разведка, чей вопрос не назван вслух,
признаётся удавшейся любым результатом.
## Ход работы
```mermaid
flowchart TD
in["вход: файл, слаг или текст"]
s1["1. вопрос и рамки<br/>сырьё без «Вопроса» — отказ"]
s2["2. разведка: документы, код,<br/>внешние источники, opsx:explore"]
s3(["3. ЧЕКПОИНТ: варианты<br/>2–4 способа, цена каждого,<br/>что становится невозможным"])
s4["4. ответ в документы канона<br/>av-dev-docs:docs"]
s5["5. задачи: завести и уточнить<br/>av-dev-tasks:tasks"]
s6["6. гейт проекта, затем коммит<br/>av-dev-git:commit"]
s7["7. закрыть разведку — av-dev-tasks:tasks,<br/>вторым коммитом учёта"]
out["исход назван: знание, задачи,<br/>отказ или «не доведена»"]
in --> s1 --> s2 --> s3
s3 -->|"выбран способ,<br/>отказ или знание"| s4
s3 -.->|"вопрос не тот"| s1
s4 --> s5 --> s6 --> s7 --> out
```
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при расхождении
прав текст.
## Плановый стоп сценария
**До чекпоинта умолчание прежнее — делать, а не спрашивать.** Развилка, найденная
по ходу разведки, не задаётся отдельным вопросом: она копится в чекпоинт, который
рядом и стоит дёшево.
Стоп здесь один, и стоит он **перед записью**. Причина в цене: пока варианты
живут в контексте, смена решения стоит абзаца; записанный в документы и разложенный
на задачи выбор стоит правки документов и разбора беклога. Второго стопа — «покажи,
что именно уедет в документы» — нет намеренно: всё, что пишет разведка, лежит в
git и читается диффом, а второй стоп на каждой разведке вырождается в ритуал
одобрения.
**Правило необратимого действует и здесь** (SKILL.md, «Когда спрашивать вне
чекпоинта»), и разведка обманчива: она кажется безобидной, а замер лезет туда, где
живут данные — прогон на боевой базе, запрос к внешнему платному источнику. Здесь
ошибка не откатывается правкой текста.
## Границы: чего разведка не делает
- **Кодом.** Ни строки, включая «маленький черновик, чтобы проверить». Замер,
требующий кода, — это отдельная задача, и её нужно назвать, а не написать по
ходу. Исключение ровно одно и оно не про изменение системы: одноразовый
**читающий** прогон (запрос, замер, скрипт в песочнице), чей результат уезжает
в ответ с провенансом и который ничего не оставляет в репозитории.
- **Приоритетом.** Заведённая задача встаёт в конец своей секции; где ей стоять
в очереди, решает человек на груминге (`av-dev-tasks:groom`). Разведка, сама
ставящая свой исход первым в беклоге, назначает приоритет тому, что только что
придумала.
- **Форматом задач и документов.** Индексы и документы руками не правятся: их
ведут `av-dev-tasks:tasks` и `av-dev-docs:docs`. Твоё — содержание ответа, их —
форма и дом.
- **Определением ценности.** «Нужно ли это делать вообще» — вопрос человека.
Разведка отвечает «как это можно сделать и чего каждый способ стоит».
- **Решением задачи.** Выбранный способ реализует сценарий решения, и запускает
его человек следующим прогоном. Перейти в него по ходу нельзя — это тот самый
переход, ради невозможности которого сценарии и разведены.
## Наблюдаемые исходы сценария
Четыре, и каждый обязан быть назван в докладе прямо. Первые три — это те самые
«заведены задачи, записано знание, отказ», которыми кончается разведка по
определению типа `research`:
- **способ выбран** — ответ записан, задачи заведены или уточнены, они готовы к
взятию. Дальше сценарий решения, следующим прогоном, и запускает его человек;
- **знание записано** — вопрос закрыт, задач он не породил: ответ ценен сам по
себе (замер, устройство внешнего формата, «так работает и менять не нужно»);
- **отказ** — проверили, проблемы нет либо подход отвергнут. **Полноправный
исход, а не пустая работа**: «не делаем и вот почему» экономит всю работу,
которая иначе была бы сделана. Причина записывается — без неё через квартал
разведку закажут заново;
- **не доведена** — вопроса нет (сырьё), рамки исчерпаны без ответа, или человек
на чекпоинте не одобрил ни одного варианта. Названо, что успели узнать и до
какой границы.
## Определение сделанного для разведки
У сценария решения оно своё (SKILL.md); здесь — короткое и другое. Разведка
сделана, когда верно всё:
1. **ответ записан по адресу, который назвала задача** — раздел «Куда ляжет
ответ». Адреса не было, а вопрос был — ты назначил адрес сам и сказал об этом
строкой;
2. **у каждого числа провенанс** — команда или условия, которыми оно получено.
Число без источника проход ревью обязан читать как условие, а не как замер, и
разведка, оставившая голые числа, вредна: по ним будут решать;
3. **отвергнутые варианты названы с причиной**. Отвергнутое без причины
возвращается на следующей разведке как новая идея;
4. задачи, которые исход породил, заведены — или явно сказано, что не породил;
5. написанное закоммичено, разведка закрыта.
## Шаги
### 1. Вопрос и рамки
Прочитай запись. У типа `research` два обязательных раздела, и оба нужны тебе
прямо сейчас: **«Вопрос»** — на что отвечаем, **«Куда ляжет ответ»** — по какому
адресу он ляжет. Адрес назван заранее не из аккуратности: ответ, не имеющий дома,
остаётся в переписке, и через квартал разведку заказывают заново.
**Адрес назначает автор записи, а не ты.** Запись из каталога без него до тебя
не доходит: `ready` требует непустыми оба раздела и откажет — это стоп со
строкой, чего не хватает, а не повод дописать за автора. Иначе исполнитель сам
назначает себе приёмку, а приёмка разведки — это и есть записанный по названному
адресу ответ.
**Адрес назначаешь ты ровно в одном случае** — когда записи нет вовсе: разведка
пришла текстом или в проекте нет учёта задач. Тогда скажи об этом строкой, а
выбирай по канону, а не по удобству:
| Что узнали | Дом ответа |
| --- | --- |
| наблюдение о внешнем мире, замер с провенансом | `docs/research/` |
| решение с ценой: намеренный отказ, дорогой откат | `docs/adr/` |
| факт об устройстве системы | тема `architecture` (или своя тема проекта) |
| граница домена, «чем проект **не** является» | `passport` |
| ответ нужен только этой работе | тело самой записи |
Раздел **«Рамки»**, если он есть, — это граница разведки: сколько копаем, какие
источники, что заведомо вне. Рамок нет, а вопрос широкий — **назначь их сам и
покажи в первой реплике**. Разведка без рамок утекает: она всегда может узнать
ещё немного, и признак «достаточно» изнутри не виден.
Здесь же проверка на «не тот вопрос»: если из записи видно, что отвечать надо на
другое, скажи это сразу, а не после разведки.
### 2. Разведка
Порядок чтения — от дешёвого к дорогому, и он не произволен:
1. **документы канона проекта** — половина вопросов уже отвечена там, и разведка,
начатая с кода, переоткрывает написанное;
2. **код и его история**`git log` по узлу отвечает на «почему так» чаще, чем
кажется;
3. **внешние источники** — документация формата, чужой опыт, спецификации;
4. **замер** — если вопрос про числа. Числа снимаются с провенансом, иначе они
бесполезны на следующем шаге.
**Скилл `opsx:explore`** — законный инструмент этого шага, если плагин в проекте
есть: он держит форму размышления и не даёт ему растечься. **В explore не пишем
код.** Вызов не разрешился — работай чтением, скажи это строкой.
Развилку разведки **не записывай вопросом** — она и есть предмет следующего шага.
### 3. Чекпоинт: варианты
**Остановись и покажи человеку способы решить.** Это плановый стоп сценария и
единственное место, где разведка ждёт ответа.
Форма — короткая, экран текста:
- **вопрос**, на который отвечаем, одной фразой (он уже есть в записи);
- **2–4 варианта**, не больше. Больше четырёх — это не выбор, а список: человек
не сравнит, а признает свою неспособность сравнить и попросит рекомендацию.
У каждого варианта: в чём суть простыми словами, **что даёт**, **чего стоит**,
**что становится невозможным** (это ловится хуже всего и стоит дороже всего);
- **рекомендация с причиной**. Человек чаще соглашается, чем выбирает заново;
- что известно **недостоверно** и как это проверить, если проверять дёшево;
- **что уедет в документы и в задачи**, если возражений нет, — одной строкой.
Это не второй стоп, а предупреждение: человек видит объём последствий там же,
где принимает решение.
Что нельзя: приносить варианты, различающиеся только реализацией; прятать
отвергнутое (отвергнутый вариант с названной причиной — половина будущего ADR);
приносить один вариант и называть это выбором.
Проверка на простой язык та же, что у чекпоинта решения: **в тексте нет `SHALL`,
нет имён файлов и функций там, где вещь называется по-русски, и нет слов, которых
нет в паспорте проекта.**
Исходы чекпоинта:
- **выбран способ** — идёшь на шаг 4, исход разведки будет «способ выбран». Кода
ты по нему не пишешь: сценарий кончается записью и коммитом;
- **ответ и есть результат** — идёшь на шаг 4, исход «знание записано» или
«отказ»;
- **вопрос не тот** — возвращаешься на шаг 1: переформулируй вопрос и скажи, что
из разведанного остаётся в силе;
- **ни один вариант не одобрен** — исход «не доведена» с причиной. Записывается
всё равно то, что узнано (шаг 4): выброшенная разведка будет заказана заново.
### 4. Ответ в документы канона
**Вызови Skill `av-dev-docs:docs`**: он владеет содержимым документов канона.
Передай ему ответ, адрес из шага 1 и провенанс каждого числа — писать содержание
за тебя он не будет, но дом, форму и вычитку держит он.
**Что именно уезжает:**
- **ответ на вопрос** — по адресу из шага 1;
- **отвергнутые варианты с причинами.** Это половина будущего ADR и единственная
защита от повторной разведки того же самого;
- **решение с ценой — в ADR**, если оно проходит триггер канона (дорогой откат,
намеренный отказ, пересмотр прежнего решения). У разведки, кончившейся без
кода, `design.md` не будет никогда, поэтому здесь ADR цитирует **записку
разведки**, а не архивный change; канон это допускает прямо, и в записи
источник называется.
**Правило принуждённого отрицания здесь не действует.** Это не синк: разведка
трогает те документы, которых коснулся её ответ, и перебирать весь канон ей
незачем. Но **названо должно быть каждое место, куда ты писал**, — доклад без
перечня адресов неотличим от доклада о ненаписанном.
**Плагина `av-dev-docs` нет** — путь в его дерево не разрешится ниоткуда, поэтому
за перечнем документов иди в **свой** reference:
[references/project-facts.md](../../review/references/project-facts.md) конвейера
ревью. `docs/adr/` и `docs/research/` в нём отсутствуют намеренно (проход ревью их
не открывает), а разведке нужны как раз они — добавь их руками. Пиши сам, скажи
строкой: «ответ записан без скилла документации — форму и вычитку не сверял
никто».
### 5. Задачи: завести и уточнить
**Вызови Skill `av-dev-tasks:tasks`.** Он владеет форматом, дедупом и индексами;
путь к его скрипту не выясняй и индексы руками не правь.
Что просишь сделать:
- **уточнить саму разведку** — если её вопрос по ходу изменился;
- **уточнить существующие задачи** — разведка часто отвечает не «что делать», а
«что в поставленном неверно»: постановка, границы в разделе «Затрагивает»,
критерии приёмки;
- **завести новые задачи**, если исход их породил. Формулировки приноси готовыми:
заголовок, «зачем», тип, границы. Нарезку на независимо полезные части и
проверку на дубли делает он — у него на это свои правила и свой сценарий.
**Пачку задач показывай списком, прежде чем заводить.** Разведка — самый лёгкий
способ надуть беклог: она порождает идеи быстрее, чем кто-либо успевает их
оценивать, а заведённая задача живёт, пока её кто-то не выкинет руками.
Плагина нет — задачи остаются **списком формулировок в докладе**, и это говорится
строкой: учёт работ остаётся за владельцем.
### 6. Гейт и коммит
**Сперва гейт проекта** — тот же, что гоняет сценарий решения, и по той же
причине: разведка только что правила документы канона и индексы задач, а это
ровно то, что машина умеет проверить (`docs.py check`, `tasks.py check --dir`,
битые ссылки). Красный гейт чинится здесь, а не оставляется следующему прогону:
он придёт за код и получит чужую поломку в наследство.
Гейта в проекте нет — скажи строкой, что записанное не проверял никто.
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
создавай и не переключай, ничего не пушь.
Сообщение — по-русски, **скиллом `av-dev-git:commit`**: форму сообщения держит
он, и здесь она не пересказывается. Вызов не разрешился — напиши сообщение сам и
скажи строкой, что форму коммита не сверял никто.
Одна разведка — один осмысленный коммит: записанный ответ и заведённые задачи
уезжают вместе, потому что порознь они полуправда.
### 7. Закрыть разведку — после коммита, не раньше
**Вызови Skill `av-dev-tasks:tasks`** и попроси закрыть запись: ответ записан —
`close --implemented`, ушла без ответа — `close --reason`, и строка уезжает в
кладбище.
**Порядок обязателен.** Закрытие удаляет файл задачи; сделанное до коммита оно
оставило бы разведку закрытой без единого следа работы, если шаг 6 упадёт. У
разведки это опаснее, чем у решения: следом работы там служит код, а здесь —
только записанный ответ. Закрытая разведка без него не оставляет следа вообще —
файл задачи удалён, ответ был в переписке.
**Закрытие тоже коммитится — вторым коммитом, тут же.** Сообщение короткое, про
учёт, а не про работу: `закрыта задача <slug>`. Правило «одна разведка — один
коммит» про работу, а учёт — не работа.
Плагина в проекте нет — **ничего не выдумывай**: скажи в докладе, что учёт задач
остаётся за владельцем, и назови исход.
## Доклад разведки
Общая форма доклада — в SKILL.md; у разведки он свой, потому что докладывать
нечего из того, о чём спрашивают решение (ни метки ревью, ни критериев приёмки,
ни архивного change). Коротко, и в нём обязательно:
- **исход** одним из четырёх слов;
- **вопрос и ответ** — по фразе на каждое. Ответ, который не сворачивается во
фразу, — признак того, что разведка отвечала не на один вопрос;
- **куда записано** — перечнем адресов, а не «документация обновлена»;
- **какие задачи заведены и уточнены** — слагами;
- **что осталось неизвестным** и чего это стоит: разведка без этой строки
сообщает «выяснено», не сообщая, что именно осталось не выяснено;
- **рамки**, если они ограничили работу: докуда копали и почему остановились.
## Тонкости
- **Ответ «зависит от» — не ответ.** Если разведка кончилась развилкой, её исход
— варианты с ценой, а не пересказ обеих сторон без рекомендации.
- **Отрицательный результат записывается так же тщательно, как положительный.**
Соблазн не писать его велик: кажется, что писать нечего. Через квартал именно
этой записи и не хватит.
- **Чужую разведку не переоткрывай молча.** Нашёл в `docs/research/` или в
`docs/adr/` ответ на свой вопрос — исход «знание записано» со ссылкой, и это
лучшая из возможных разведок: она стоила одного чтения.
@@ -0,0 +1,411 @@
# Сценарий «решение»
Способ решения известен, спорно только как. Проводит задачу от постановки до
закрытия и **пишет код**: цикл Spec Driven Development с одним плановым стопом —
объяснением после ревью дизайна.
Сценарий выбирается развилкой на входе скилла ([SKILL.md](../SKILL.md), раздел
«Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его
ход; общее для обоих сценариев — вход, обращение к соседним плагинам, правило
записанного вопроса, правило необратимого — живёт в SKILL.md и тут не
пересказывается.
**OpenSpec — жёсткая предпосылка именно этого сценария** (SKILL.md,
«Предпосылки»): на нём стоят шаги 2, 6 и 8, проход `review-specs` и ревью
дизайна.
Тонкая обёртка над каноническими скиллами `opsx:propose` / `opsx:apply` /
`opsx:archive` — зови их через Skill, не переизобретай их шаги. Ревью — скилл
`av-dev-code:review`; он же держит правило выбора метки, а называет её агент
`review-scope` — один раз на задачу, для обеих стадий ревью.
## Ход работы
```mermaid
flowchart TD
in["сценарий выбран: решение"]
s1["1. прочитать задачу<br/>критерии приёмки выписать сразу"]
s2["2. opsx:propose — change, дельта-спеки, tasks.md"]
s3["3. разметка — review-scope:<br/>размер, сложность, метка, план тем"]
s4["4. ревью дизайна, состав по метке<br/>+ отработка замечаний"]
s5(["5. ЧЕКПОИНТ: объяснение<br/>в чём проблема, как решаем,<br/>чем рискуем"])
s6["6. opsx:apply — код, гейт,<br/>поведенческая верификация"]
s7["7. ревью кода, та же метка<br/>+ отработка замечаний"]
s8["8. opsx:archive"]
s9["9. синк документации — av-dev-docs:docs"]
s10["10. коммит работы — av-dev-git:commit"]
s11["11. закрыть задачу — av-dev-tasks:tasks,<br/>вторым коммитом учёта"]
in --> s1
s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 --> s11
s3 -.->|"план задачи: та же метка"| s7
s5 -.->|"скорректировать:<br/>меняются дельта-спеки"| s3
s7 -.->|"находка отменяет дизайн:<br/>меняются дельта-спеки"| s3
```
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при
расхождении прав текст.
## Наблюдаемые исходы сценария
Четыре, и каждый обязан быть назван в докладе прямо:
- **сделана** — определение сделанного выполнено целиком;
- **не доведена** — с причиной и с записанным вопросом; что именно сделано и до
какой границы, названо явно. Сюда же попадает чекпоинт, на котором человек
решение не одобрил;
- **оказалась крупнее задачи** — распознаётся **до заведения change**, иначе его
придётся выбрасывать. Дальше — декомпозиция, и это не работа этого скилла;
- **нужна разведка** — очевидного способа решения нет, и это выяснилось уже в
работе. Стоп с названной причиной; кода не написано ни строки **намеренно**.
Разведка идёт следующим прогоном.
## Определение сделанного
Задача сделана, когда верно всё:
1. гейт проекта зелёный;
2. ревью проведено, **план прогона сверен с исходом по каждой теме**, темы без
отчёта и без дома названы в границах покрытия;
3. решение прошло чекпоинт и не разошлось с одобренным — либо разошлось, и
чекпоинт был пройден заново;
4. change заархивирован, дельты влиты в актуальные спеки;
5. коммит сделан в текущую ветку;
6. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван
оракул и наблюдаемый исход** — «прогнал вот это, увидел вот то». Это **доклад,
а не сертификация: приёмка — не работа этого скилла.** Исполнитель, ставящий
себе галочку «принято», проверяет свою работу своим же взглядом — по границе
это может делать только приёмщик, разведённый с исполнителем. Критерии приходят
снаружи; скилл их не сочиняет и не занижает. Расхождение «по каждому критерию
исход есть, а суть задачи не достигнута» — дефект критериев, и о нём
сообщается, а не молча дорабатывается.
## Шаги
### 1. Прочитать задачу
Прочитай запись и связанные спеки и черновики.
Проект даёт задаче **критерии приёмки** — выпиши их сразу: на шаге 2 они уезжают
в `tasks.md` change. Файл задачи может быть удалён до коммита, а критерии обязаны
его пережить.
Здесь же проверка на «крупнее задачи»: видно, что одним заходом это не
мерджится, — объявляй исход **до** заведения change.
### 2. Завести change — `opsx:propose`
Вызови Skill `opsx:propose`. Получаем `proposal.md`, дизайн, дельта-спеки
(`ADDED`/`MODIFIED`/`REMOVED Requirements`), `tasks.md`. Каждое `### Requirement`
содержит `SHALL`/`MUST`; структурные заголовки английские, сценарии
`GIVEN/WHEN/THEN`. Прогони `openspec validate --strict <id>`.
Критерии приёмки задачи, если они были, копируются в `tasks.md` отдельным блоком.
Задаче предшествовала разведка — её записка и отвергнутые варианты **уже
записаны** в документах канона (`docs/research/`, `docs/adr/`): сошлись на них из
`design.md`, а не переписывай второй раз. Варианты, разобранные без разведки
(способ был очевиден, но у него оказались оттенки), — в `design.md`, с причиной
отказа по каждому отвергнутому.
**`proposal.md` пишется так, чтобы его понял человек, не читавший спек.** Это не
стилистическое пожелание: из него собирается чекпоинт шага 5, и переписывать его
там заново значит завести второй дом для одного объяснения. Требование стоит в
`openspec/config.yaml`, `rules.proposal` — то есть применяется в момент
порождения артефакта, а не вспоминается после.
### 3. Разметка задачи — агент `review-scope`
**Один запуск на всю задачу, и он обслуживает обе стадии ревью.** Запусти
агента `review-scope`, дав ему корень проекта, идентификатор change, базу диффа и
запись задачи. Кода на этот момент нет, и это условие его работы, а не помеха.
Он возвращает **план задачи**:
- **размер** (малое / среднее / крупное) и **сложность** (знакомое /
незнакомое), каждое с обоснованием по факту;
- **метку** как максимум по двум осям: `small`, `medium` или `large`;
- **состав ревью дизайна** — что звать на шаге 4;
- **таблицу тем** «тема → дом → глубина → кто закрывает» — для шага 7;
- разнесение документов проекта по трём категориям и строку про директивы.
**Метку выбираешь не ты.** Раньше состав ревью дизайна называл сам оркестратор —
то есть тот, кто только что довёл предложение до `propose`. Разведённости с
автором в этой точке не было вовсе; теперь есть.
**План держи в контексте до конца задачи.** На диск он не пишется: файл-план стал
бы четвёртым артефактом рядом с `proposal.md`, `tasks.md` и `design.md`, пережил
бы задачу и разошёлся бы с ней молча. Прервался прогон — повтори шаг 3, это самый
дешёвый его проход.
**Разметка повторяется ровно в одном случае** — если правки изменили сами
**дельта-спеки**: план выведен из них, и план по отменённым требованиям назовёт
не те темы. Во всех прочих случаях, включая переделку формы кода на шаге 7,
метка остаётся прежней.
### 4. Ревью дизайна — ДО кода, состав по метке
Вызови Skill **`av-dev-code:review`**, дав ссылку на change `<id>`,
**план разметки с шага 3** и указание, что это ревью дизайна.
Состав приходит планом, а не решается здесь:
| Метка | Проходы на предложении |
|---|---|
| `small` | `specs` |
| `medium` | `specs`, `rubric` |
| `large` | `specs`, `rubric`, `architecture` + вопрос автору о трёх формах решения |
`review-specs` в режиме «дизайн ДО кода» идёт **на каждой задаче**: это самый
дешёвый проход конвейера, и он ловит то, что на готовом коде уже не чинят.
Остальные включаются меткой, потому что стадия стоит на каждой задаче и каждый
лишний проход здесь умножается на число задач.
Смысл стадии: архитектурная находка на готовом коде стоит переписывания и потому
игнорируется — та же находка здесь стоит абзаца обсуждения. Если `review-rubric`
запускался, перенеси его рубрику в `tasks.md` как приёмочные критерии; там же уже
лежат критерии от постановки, если они были.
**Отработка замечаний, и она идёт до чекпоинта, а не после:**
- мелочь и явные улучшения — правь сам в спеках и дизайне;
- развилки (компромисс, scope, инвариант) — **не в запись, а в чекпоинт**: он
следующим шагом, и это ровно то, ради чего он поставлен здесь;
- после правок перепрогони `openspec validate --strict <id>`.
### 5. Чекпоинт: объяснение
**Остановись и объясни человеку, что происходит.** Единственный плановый стоп
этого сценария, и он обязателен для всякой задачи.
Он стоит **после** ревью дизайна намеренно. Человек читает объяснение, уже
просеянное машиной: то, что поймал бы `review-specs`, до него не доходит, а
внимание — самый дорогой ресурс процесса, и тратить его на выловимое машиной
нельзя.
**Объяснение не сочиняется заново — оно собирается из артефактов**, `proposal.md`
и `design.md`. Третий пересказ был бы третьим домом одного и того же и разошёлся
бы с обоими. Что показываешь:
- **в чём проблема** — словами домена из паспорта, без имён модулей и функций;
- **как решаем** — суть одним абзацем. Не пересказ дельта-спек: спека нормирует,
а здесь объясняют;
- **что человек увидит иначе**, когда это будет сделано;
- **чего мы намеренно не делаем** и почему — граница scope ловится хуже всего;
- **чем рискуем и что осталось нерешённым** — сюда съезжаются развилки,
накопленные до этого места, и находки ревью с пометкой `развилка`;
- **что дальше**, если возражений нет.
Проверка на «простой язык» одна и механическая: **в тексте нет `SHALL`, нет имён
файлов и функций там, где вещь называется по-русски, и нет слов, которых нет в
паспорте проекта.** Не проходит — переписывай, а не объясняй, почему иначе
нельзя.
Длина — экран. Длинное объяснение не читают, а пролистывают, и чекпоинт
превращается в ритуал одобрения.
Три исхода:
- **согласен** — идёшь на шаг 6;
- **скорректировать** — правишь спеки и дизайн по сказанному. Изменились
**дельта-спеки** — повтори шаг 3 (разметка выведена из них) и ту часть ревью
дизайна, которой касается правка; затем чекпоинт **заново**. Правка внутри
дизайна без спек — повтори только чекпоинт;
- **не одобрено** — исход «не доведена» с причиной. Change остаётся
незаархивированным, задача не закрывается, ничего не коммитится наполовину.
### 6. Написать код — `opsx:apply`
Вызови Skill `opsx:apply` для реализации `tasks.md`. Код — по конвенциям проекта
(каталог `docs/conventions/`). Меняешь схему — обнови её описание в документации
тем же change, если проект этого требует: гейт обычно это проверяет.
Прогони гейт и добейся зелёного — он же гейт следующего шага.
**Поведенческая верификация.** Если задача меняет реальное поведение (новый
эндпоинт, разбор входа, схема, форма ответа) — зелёных юнит-тестов мало. Подними
изменение вживую командой из раздела команд `CLAUDE.md` и прогони сценарий.
Пропусти только для чисто внутренних правок без наблюдаемого рантайма.
**Сервис не оставляем лежать.** Если запуск упал — почини или откати до конца
шага.
### 7. Ревью кода — та же метка
Вызови Skill **`av-dev-code:review`**, дав ссылку на change `<id>`,
базу диффа, **план разметки с шага 3** и режим запуска.
**Метку ты не выбираешь, и это правило, а не упрощение.** Её назвал
`review-scope` ещё на шаге 3 — по размеру и сложности, с обоснованием по каждой
оси. Причина в разведённости: ты только что написал этот код, и решать, насколько
глубоко его проверять, тебе нельзя — под давлением «я почти закончил» решение
известно заранее. Правило выбора живёт в скилле конвейера —
`av-dev-code:review`, `references/review-levels.md`; проектные
триггеры — в `docs/review.*`, подраздел «Триггеры метки».
**Метка не пересматривается по факту диффа.** Дифф может выйти крупнее, чем
ожидалось при разметке, — это не повод её поднимать: пересмотр означал бы второй
запуск разметчика, ровно то, ради устранения чего он и переехал на шаг 3.
**Считаешь метку заниженной — скажи это в докладе строкой, а не переспорь.**
Разметчик вправе и поднять, и понизить; твоё несогласие это факт для человека, а
не команда конвейеру. Место, где такое несогласие превращается в изменение
правил, — журнал дефектов `docs/review.md`, и только постфактум.
**Плана нет — ревью кода не запускается.** Триаж требует план обязательным
входом: без него он не может сверить, все ли размеченные темы вернули отчёт, а
эта сверка — единственная защита от молчащего пропуска. Потерял план (прервалась
сессия, ушёл контекст) — повтори шаг 3, а не гони прогон без него.
**Режим по умолчанию — `по графу`, и обосновывать его не надо.** Конвейер сам
знает свои рёбра: гейт открывает опиниативные проходы, проходы с пометкой «держит
машину» идут цепочкой (иначе замеры портят друг друга и находка выглядит
доказанной), триаж — сток. Просить **`линейно`** нужно только по причине, и она
называется строкой: так сказал оператор; машина занята чем-то ещё; идёт разбор
самого конвейера.
Скилл сам гоняет гейт, нужные проходы и обязательный триаж. Возвращает отчёт с
потолком 7 пунктов, разметкой `Действие: инлайн | развилка` и секцией границ
покрытия.
**Сверь план прогона с исходом, прежде чем коммитить.** Отчёт начинается планом
разметчика — таблицей «тема → дом → глубина → кто закрывает», — и против каждой
темы обязан стоять исход. Тема без отчёта и тема без дома — разные вещи, и обе
должны быть названы. Реестр короткий (шесть тем ядра плюс свои) — сверка стоит
одного взгляда.
#### Отработка, и здесь появляется одно новое правило
Помеченное `инлайн` чини сам и не логируй. `развилка` — вопросом в запись (он уже
сформулирован триажем, его остаётся перенести). После правок — снова гейт.
**Находка, отменяющая одобренный дизайн, отменяет и одобрение.** Признак
проверяемый: **меняются ли дельта-спеки**.
- не меняются — находка внутри дизайна, дожимай сам, это обычная отработка;
- меняются — решение стало другим, а одобрено было прежнее. Повтори шаг 3
(разметка выведена из дельта-спек) и **вернись на чекпоинт шага 5** с тем, что
изменилось и почему.
**Это правило старше правила о развилке.** Находка класса `развилка`, чьё
основание — «надо менять спеку», подпадает под оба; побеждает возврат на
чекпоинт, а вопрос в запись при нём остаётся, но возврата не заменяет. Иначе
одобренный дизайн переделывался бы записанным вопросом, то есть молча.
Тихо переделать утверждённое нельзя. Чекпоинт, который можно обойти находкой
ревью, не значит ничего, а человек при этом уверен, что одобрил именно то, что
уехало в коммит.
**Урожай — списком, не задачами.** Отложенные находки (реальный `major` не для
этого мерджа, развилка, решённая «потом», пачка `nit`) собери в секцию доклада
`Урожай`: формулировка, оракул, провенанс. Задачи из него **заводит не этот
скилл** — их заводит `av-dev-tasks:tasks` своим сценарием «задачи из ревью и
аудита»: своя нарезка, свой формат, свои правила дублей. Твоя обязанность — не
потерять и передать.
**Границы покрытия из отчёта не выбрасывай** — они уезжают в финальный доклад
сжатой строкой. Отчёт, из которого исчезло «что проверить было невозможно»,
превращается в ложное ощущение проверенности.
**Отчёт триажа сохрани вместе с change (`openspec/changes/<id>/review/`; шаг 8
унесёт его в архив вместе с change) — это обязательно, а не «если удобно».** По
нему потом видно, что было найдено и что из этого осталось в урожае. И это
единственный **независимый** артефакт о составе прогона: своей прозе здесь верить
нельзя — она написана тем же, кто мог проход и пропустить.
### 8. Архивировать — `opsx:archive`
Вызови Skill `opsx:archive`: change уезжает в архив, дельты вливаются в
актуальные спеки. Не пропускай `openspec validate --strict` перед этим.
### 9. Синк документации
**Вызови Skill `av-dev-docs:docs`**: он владеет содержимым документов канона и
ведёт чек-лист синка.
**Правило одно и оно жёсткое: принуждённое отрицание.** Доклад обязан назвать
**каждый** документ канона — либо чем он обновлён, либо «не требуется, потому
что…». Нетронутые группируются одной строкой с общей причиной. Список триггеров
прозой уже проверен на живом проекте и дал 6 записей ADR на 43 изменения;
работает только обязательное отрицание.
**Список документов и их триггеров здесь не дублируется** — он в чек-листе скилла
`av-dev-docs:docs`, и копия уже однажды разошлась с оригиналом, потеряв два
триггера.
**Плагина `av-dev-docs` в проекте нет** — путь в его дерево не разрешится ниоткуда,
поэтому за списком иди в **свой** reference:
[references/project-facts.md](../../review/references/project-facts.md)
конвейера ревью перечисляет все документы канона с их предметом. Пройди по этому
перечню — каждый документ получает строку, отрицание остаётся обязательным.
**Двух домов в том перечне нет намеренно, а синку они нужны: `docs/adr/` и
`docs/research/`.** Проход ревью их не открывает — процессные, — но ADR как раз
**главный выход синка**: решение, принятое по ходу задачи, без этой строки
теряется систематически. Добавь их к перечню руками: `adr/` — решение с ценой,
принятое в этой задаче; `research/` — если по ходу узналось новое о внешнем мире
(записку разведки, предшествовавшей задаче, пишет не этот сценарий).
Триггеры при этом ты знаешь хуже, и это называется в докладе строкой: «синк
сделан по перечню документов, без списка триггеров — плагина `av-dev-docs` нет».
Канона в проекте тоже нет — назови это исходом и предложи `av-dev-docs:canon`.
### 10. Коммит
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
создавай и не переключай, ничего не пушь.
Сообщение — по-русски, **скиллом `av-dev-git:commit`**: форму сообщения держит
он, и здесь она не пересказывается. Вызов не разрешился — плагина в проекте нет:
напиши сообщение сам и скажи строкой доклада, что форму коммита не сверял никто.
Одна задача — один осмысленный коммит.
### 11. Закрыть задачу — **после коммита, не раньше**
**Вызови Skill `av-dev-tasks:tasks`** и попроси закрыть задачу как реализованную —
он владеет форматом и двигает строку индекса сам. Путь к его скрипту не выясняй и
индексы руками не правь: мост между плагинами — вызов скилла, а не путь.
**Порядок обязателен.** Закрытие удаляет файл задачи; сделанное до коммита оно
оставило бы задачу закрытой без единого следа работы, если шаг 10 упадёт.
**Закрытие тоже коммитится — вторым коммитом, тут же.** Удаление файла задачи и
правка индексов (их имена знает `av-dev-tasks`, не ты) — это правки в рабочем
дереве, и оставить их незакоммиченными нельзя: закрытие, не доехавшее до основной
ветки, оставит задачу открытой молча, а опора «индексы под git показывают, что и
когда закрыто» без коммита — пустые слова. Сообщение короткое, про учёт, а не про
работу: `закрыта задача <slug>`. Это второй коммит осознанно: правило «одна задача
— один осмысленный коммит» про работу, а учёт — не работа.
Плагина в проекте нет — вызов не разрешится. Тогда **ничего не выдумывай**: скажи
в докладе, что учёт задач остаётся за владельцем, и назови исход.
## Доклад решения
Общее ядро доклада — в SKILL.md; сверх него сценарий решения обязан назвать:
- **что было одобрено на чекпоинте и совпало ли с тем, что уехало в коммит** —
расхождение здесь называется прямо, даже если оно мелкое;
- ссылка на архивный change и хеш коммита;
- по каждому критерию приёмки, если они были: **оракул и наблюдаемый исход**
это доклад приёмщику, а не отметка «принято»;
- **`Урожай`** — отложенные находки списком (формулировка, оракул, провенанс);
- **одна строка границ покрытия**: какая метка и режим гонялись, какие проходы не
запускались и что проверить было невозможно. Доклад без неё сообщает
«проверено», не сообщая, что именно.
## Тонкости сценария
- Гейт блокирует: пока он красный, опиниативные проходы не запускаются. Чинить и
перезапускать, а не «посмотреть заодно».
- Стиль правок — заточка под проект и конвенции, right-size, без золочения.
- **Занизить метку ревью, пропустить тему или проскочить чекпоинт — самый дешёвый
способ «ускориться», и он же самый дорогой по последствиям.** Защита устроена
так, что регулятора у тебя нет: метку выбирает разметчик **до того**, как ты
написал код, план сверяется по темам, непокрытое называется строкой, а
расхождение с одобренным — отдельным пунктом доклада.
- **Заведение задач из урожая ревью — не твоя работа.** Отложенные находки
отдаются **списком**; превращает их в задачи `av-dev-tasks:tasks`, у него на
этот вход отдельный сценарий «задачи из ревью и аудита». Плагина нет — урожай
остаётся списком в докладе, и это говорится строкой.
- **Способ решения ты не выбираешь.** Он приходит известным: из постановки, из
разведки, от человека. Выбор между двумя подходами с разной ценой делается в
разведке, у своего чекпоинта, — не по ходу этого сценария.