diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4bc9fed..da2d8d3 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -18,7 +18,7 @@ { "name": "av-dev-code", "source": "./av-dev-code", - "description": "Решение одной задачи от постановки до закрытия скиллом resolve — полный цикл Spec Driven Development с двумя плановыми остановками: чекпоинт вариантов у исследовательской задачи и чекпоинт с объяснением человеческим языком после ревью дизайна у всякой. Между ними работа идёт без согласований. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. Требует OpenSpec и сам его заводит скиллом openspec. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой." + "description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария два, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой." }, { "name": "av-dev-git", diff --git a/DECISIONS.md b/DECISIONS.md index a4b92a2..e6f75b6 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -3713,3 +3713,69 @@ change нет — берём источником актуальные спек на вопрос «по какой записи повышать», а не «сделаны ли шаги по существу». Машина, приписывающая недостающее число сама, объявляет проект приведённым к формату, которого никто не проходил. + +## 61. Разведка и решение — два сценария одного скилла, а не два скилла (2026-08-11) + +Скилл `resolve` вёл обе работы одной цепочкой: у исследовательской задачи были +свои три шага и свой чекпоинт вариантов, после которого она **вливалась в общую +ветку** и продолжалась кодом. Разведка тем самым была не работой со своим +исходом, а прологом к коду: её ответ оседал в `design.md` будущего change, и +разведка, кончившаяся знанием, документов проекта не касалась вовсе. + +Сперва я развёл их на два скилла — `resolve` и `research`, с исходом и стопом с +обеих сторон. Через час работы стало видно, чем это плохо: **классифицировать +задачу приходится человеку до вызова**, а «есть ли у неё очевидный способ +решения» видно только после чтения записи. Разделение переносило самое трудное +суждение туда, где для него меньше всего данных. + +**Решено: точка входа одна, сценария два, выбирает сценарий скилл.** Оба сценария +живут справочниками — `references/solve.md` и `references/research.md`, — а в +`SKILL.md` остались вход, развилка и правила, не зависящие от сценария. Тем же +приёмом сложен скилл задач: общая часть в `SKILL.md`, алгоритм каждого типа в +`references/task-*.md`. + +**Порознь и одинаково — это отдельное решение.** Сперва разведка уехала в +справочник, а решение осталось в теле скилла: так вышло само, потому что решение +там уже лежало. Асимметрия читается как старшинство — сценарий в теле выглядит +основным, а сценарий в справочнике оговоркой, — и удерживает шестисотстрочный +файл, который грузится целиком даже ради разведки. + +**Что у разведки появилось своего.** Исход — знание, а не пролог: ответ уезжает в +документы канона (`av-dev-docs:docs`), задачи заводятся и уточняются +(`av-dev-tasks:tasks`), написанное коммитится, запись закрывается. Кода сценарий +не пишет вовсе. OpenSpec ему не нужен — это единственное место скилла, где тот не +предпосылка. + +**Переход между сценариями — событие с названным исходом.** Решение, упёршееся в +незнание способа, останавливается; разведка, выбравшая способ, доводится до конца +и **не переходит в код тем же прогоном** — следующий запускает человек. Причина +не в церемонии: разведка только что переписала постановку, и брать её в работу +тем же заходом значит решать за человека, стоит ли делать это сейчас, — а это +приоритет. + +**Канон пришлось тронуть, и это версия 14.** ADR цитировал только архивный +`design.md`. У решения, принятого разведкой, `design.md` нет по построению — +change по нему не будет никогда, — и такое решение либо не попадало в `adr/` +вовсе, либо попадало сочинённым заново. Теперь источников два, и оба называются в +записи. + +### Что из этого следует + +204. **Разделять работы стоит по моменту для человека, а не по роду работы.** + У разведки и решения он разный: варианты обсуждают до первого требования, + объяснение — после ревью дизайна. Всё остальное различие (пишем код или нет) + из этого уже следует. +205. **Точку входа не разделяют по признаку, который виден только внутри.** + Классификация, требующая прочитать запись, не может быть условием вызова: + человек либо ошибётся, либо прочитает запись сам — и тогда скилл ему не + нужен. +206. **Сценарий в справочнике дешевле скилла.** Скилл стоит описания, границ, + копии правил и своего места в графе вызовов; справочник наследует их у + хозяина. Заводить второй скилл имеет смысл, когда его зовут отдельно, а не + когда он просто длинный. +207. **Равные сценарии лежат одинаково.** Оставить один в теле скилла, а второй + вынести — значит назначить первому старшинство, которого в замысле нет. + Читатель это старшинство считывает, даже когда о нём не сказано ни слова. +208. **Работа без своего исхода вырождается в пролог.** Разведка, кончавшаяся + переходом к коду, не имела причины писать в документы: её ответ и так уезжал + в `design.md`. Дом для исхода — вот что делает работу работой. diff --git a/README.md b/README.md index 6eb8924..0c94118 100644 --- a/README.md +++ b/README.md @@ -36,19 +36,28 @@ очереди, и живёт он в индексе. Интерактивный: разбирает вопросы пачкой, переоценивает порциями по 5–8, расставляет верх очереди с доводом на каждое движение. -- **av-dev-code** — код по задачам: решение одной задачи и его проверка. - Владеет `openspec/`. **Требует OpenSpec и сам его заводит.** +- **av-dev-code** — работа по задачам: разведка, решение и проверка сделанного. + Владеет `openspec/`. **Требует OpenSpec и сам его заводит** — кроме сценария + разведки, которому он не нужен. - `openspec` — завести, настроить и **проверить** `openspec/` в проекте: `openspec init`, замена примера в `config.yaml` настройкой канонической формы, скрипт `openspec.py` (форма файла + сверка слепка с живой версией инструмента). Каталог принадлежит конвейеру, а не канону: без конвейера он проекту не нужен, и `docs.py` о нём молчит; - - `resolve` — одна задача от постановки до закрытия. Обычная идёт циклом SDD - с **чекпоинтом после ревью дизайна**: объяснение человеческим языком, повод - скорректировать ход решения. Исследовательская начинается с `opsx:explore` и - **чекпоинта вариантов** — способы решить, цена каждого, рекомендация; выбор - оседает по адресу, который назвала сама задача. Между чекпоинтами — без - согласований; + - `resolve` — одна задача от постановки до закрытия. **Точка входа одна, а + сценария два, и выбирает сценарий сам скилл, прочитав постановку:** + классифицировать задачу до вызова человек всё равно не может — «есть ли + очевидный способ решения» видно после чтения записи. + **Решение** идёт циклом SDD с чекпоинтом после ревью дизайна: объяснение + человеческим языком, повод скорректировать ход. + **Разведка** (тип `research`, сырая идея, мутная постановка) кода не пишет + вовсе: её чекпоинт — варианты, 2–4 способа решить с ценой каждого, — стоит до + первого написанного требования, а исход уезжает в документы канона и в + задачи. Выбранный способ реализуется **следующим прогоном**, и запускает его + человек: смена сценария по ходу — событие с названным исходом, а не тихий + поворот. Оба сценария лежат справочниками и одинаково — `references/solve.md` + и `references/research.md`; в самом скилле только вход, развилка и правила, + не зависящие от сценария. OpenSpec нужен решению, разведке — нет; - `review` — конвейер ревью **по темам**: документ проекта либо заводит тему проверки, либо питает чужую тему источником, либо процессный и в ревью не читается вовсе. Разметка идёт **один раз на задачу**, сразу после @@ -69,9 +78,9 @@ ```mermaid flowchart TB - subgraph pipe["av-dev-code — исполнение, требует OpenSpec"] + subgraph pipe["av-dev-code — исполнение; сценарий решения требует OpenSpec"] direction LR - tp["resolve
2 чекпоинта человеку"] --> rp["review
10 агентов-проходов"] + tp["resolve
2 сценария: разведка и решение"] --> rp["review
10 агентов-проходов"] osp["openspec
заводит и проверяет openspec/"] end subgraph docsp["av-dev-docs — документация, владеет docs/"] diff --git a/TODO.md b/TODO.md index ba398b3..b859810 100644 --- a/TODO.md +++ b/TODO.md @@ -20,7 +20,7 @@ цикл SDD, конвейер ревью, OpenSpec), `av-dev-git`. Общее, что нужно нескольким дословно, живёт домом в `shared/` и уезжает копиями. -Канон документов — **версия 13**; формат задач — **версия 1**, своя и со своим журналом. Живые проекты стоят на 2–3 и на плагине +Канон документов — **версия 14**; формат задач — **версия 1**, своя и со своим журналом. Живые проекты стоят на 2–3 и на плагине `av-dev-pm`, которого больше нет. Бумажная часть закрыта аудитом четырёх плагинов и четырьмя пропусками правок @@ -42,7 +42,7 @@ - [ ] удалить проектные копии: `.claude/skills/healthlog-{task,review}-pipeline` и девять `.claude/agents/healthlog-review-*.md`. Они прошлого поколения и после переезда указывают на документы, которых уже не будет -- [ ] `av-dev-docs:canon` в режиме `adopt` — он приведёт проект к канону 13 +- [ ] `av-dev-docs:canon` в режиме `adopt` — он приведёт проект к канону 14 сразу, картой и с подтверждением. Файл-в-файл здесь не расписан: раскладку знает скилл, и второй перечень разошёлся бы с ним - [ ] каталог задач — в `tasks/` корня (канон 11), не в `docs/tasks/`, без @@ -84,9 +84,14 @@ ## 4. Конвейер: что осталось после `resolve` -Сам скилл написан (`av-dev-code:resolve`, два чекпоинта, ветка разведки), -`task-batch` удалён. Осталось то, что на бумаге не проверяется: +Сам скилл написан (`av-dev-code:resolve`, два сценария — разведка и решение, +по чекпоинту у каждого), `task-batch` удалён. Осталось то, что на бумаге не +проверяется: +- [ ] прогнать сценарий разведки на живой задаче: он написан целиком на бумаге и + не исполнялся ни разу. Самое неизвестное — выбор сценария на входе (не + уедет ли всё в решение, потому что «способ вроде понятен») и объём того, + что разведка пишет в документы - [ ] перемерить скилл `review` тем же вопросом, что и проект целиком: сколько из его стадий реально смотрятся глазами. Тысяча строк, и весь автоматический участок между чекпоинтами держится на них diff --git a/av-dev-code/.claude-plugin/plugin.json b/av-dev-code/.claude-plugin/plugin.json index f0bf1a1..8b5acd6 100644 --- a/av-dev-code/.claude-plugin/plugin.json +++ b/av-dev-code/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "av-dev-code", - "description": "Решение одной задачи от постановки до закрытия скиллом resolve — полный цикл Spec Driven Development с двумя плановыми остановками: чекпоинт вариантов у исследовательской задачи и чекпоинт с объяснением человеческим языком после ревью дизайна у всякой. Между ними работа идёт без согласований. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. Требует OpenSpec и сам его заводит скиллом openspec. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.", + "description": "Одна задача от постановки до закрытия скиллом resolve: точка входа одна, сценария два, и выбирает сценарий сам скилл, прочитав постановку. Сценарий решения — полный цикл Spec Driven Development с плановым чекпоинтом после ревью дизайна: объяснение человеческим языком, повод скорректировать ход решения. Сценарий разведки (тип research, сырая идея, мутная постановка) кода не пишет и change не заводит: его чекпоинт вариантов стоит до первого написанного требования, а исход уезжает в документы канона и в задачи; выбранный способ реализуется следующим прогоном, который запускает человек. Смена сценария по ходу — событие с названным исходом, а не тихий поворот. Плюс конвейер ревью с детерминированным гейтом, сверкой со спеками, враждебными постановками, эксплуатационным постмортемом и обязательным триажем. OpenSpec нужен сценарию решения, и плагин сам его заводит скиллом openspec; разведка обходится без него. Задача принимается и обычным текстом. Плагины av-dev-docs и av-dev-tasks опциональны: первый даёт документы канона, из которых проходы читают проектную конкретику, второй — учёт задач; без них прогон деградирует поразрядно и называет это строкой.", "author": { "name": "Anton Vakhrushev", "email": "anwinged@gmail.com" diff --git a/av-dev-code/skills/resolve/SKILL.md b/av-dev-code/skills/resolve/SKILL.md index 41e7c2c..98fe8d4 100644 --- a/av-dev-code/skills/resolve/SKILL.md +++ b/av-dev-code/skills/resolve/SKILL.md @@ -1,29 +1,42 @@ --- name: resolve -description: "Решить одну задачу от постановки до закрытия. На входе путь к файлу задачи, её слаг или просто текст. Обычная задача идёт циклом Spec Driven Development: opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие. Исследовательская (тип research, сырая идея, мутная постановка) начинается раньше: opsx explore и чекпоинт вариантов — два-четыре способа решить, с ценой каждого и рекомендацией; выбор оседает по адресу, который назвала сама задача. Между чекпоинтами работа идёт без согласований. Использовать, когда просят взять, сделать или решить задачу, довести идею до реализации, разобраться с записью из беклога." +description: "Взять одну задачу и довести её до закрытия. Одна точка входа, два сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ решения известен — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога." --- -# Решение одной задачи +# Работа над одной задачей -Проводит **одну** задачу от постановки до закрытия. Между плановыми -остановками — без согласований: механику не обсуждаем, делаем. +Проводит **одну** задачу от постановки до закрытия. Вокруг планового стопа — без +согласований: механику не обсуждаем, делаем. -Тонкая обёртка над каноническими скиллами `opsx:explore` / `opsx:propose` / -`opsx:apply` / `opsx:archive` — зови их через Skill, не переизобретай их шаги. -Ревью — скилл `av-dev-code:review`; он же держит правило выбора -метки, а называет её агент `review-scope` — один раз на задачу, для обеих стадий -ревью. +**Сценария два, а точка входа одна.** Какой из них идёт, решает **скилл**, +прочитав постановку, а не человек до вызова: «есть ли у задачи очевидный способ +решения» видно после чтения записи, и требовать этого суждения от вызывающего +значит требовать его раньше, чем оно возможно. + +| Сценарий | Когда | Чем кончается | +| --- | --- | --- | +| **решение** | способ известен, спорно только как | код, ревью, архив, коммит, закрытие | +| **разведка** | способа нет: тип `research`, сырая идея, мутная постановка | ответ в документах, задачи, коммит, закрытие | + +Ход каждого сценария живёт своим справочником: **решение** — +[references/solve.md](references/solve.md), **разведка** — +[references/research.md](references/research.md). Здесь только общее: вход, +развилка, правила, которые не зависят от сценария. Сценарии лежат порознь и +одинаково, потому что привилегированного среди них нет: тот, что жил бы прямо +здесь, читался бы как основной, а второй — как оговорка. ## Предпосылки -- **OpenSpec и скиллы `opsx:*` — жёсткая предпосылка, а не опция.** На них стоят - шаги 2, 6 и 8, шаг Р2 разведки, проход `review-specs` и ревью дизайна (они - завязаны на `openspec/changes//specs/*/spec.md` и на +- **OpenSpec и скиллы `opsx:*` — жёсткая предпосылка сценария решения**, а не + опция. На них стоят его шаги 2, 6 и 8, проход `review-specs` и ревью дизайна + (они завязаны на `openspec/changes//specs/*/spec.md` и на `openspec validate --strict`). **Проект без OpenSpec этим скиллом не ведётся** — - подключай OpenSpec, а не вырождай цикл; почему ветка деградации здесь не + подключай OpenSpec, а не вырождай цикл сценария; почему ветка деградации здесь + не пишется, сказано в `av-dev-code:review`, раздел «Предпосылки», и дом у этого довода там. Заводить руками не надо: каталог и настройку в `config.yaml` - делает скилл `av-dev-code:openspec`. + делает скилл `av-dev-code:openspec`. **Сценарию разведки OpenSpec не нужен** — + она не заводит change; `opsx:explore` берётся, если плагин есть. - **Проектные копии этих скиллов и агентов удаляются при установке плагина** (`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом @@ -91,74 +104,87 @@ description: "Решить одну задачу от постановки до когда сверять уже не с чем. **`ready` отказал — это исход, а не препятствие для тебя.** Скажи, чего не -хватает, и остановись: дописывать чужую запись за автора не твоя работа, а у -сырья (`research` без раздела «Вопрос») и дописывать нечего — там сперва нужен -вопрос. Исход — «не доведена», с названной причиной. +хватает, и остановись: дописывать чужую запись за автора не твоя работа. Исход — +«не доведена», с названной причиной. + +**Отказ `ready` сценарий не выбирает.** Запись `research` без раздела «Вопрос» +(сырьё) — отказ и здесь: у неё нет вопроса, и разведывать нечего. Плагина `av-dev-tasks` в проекте нет или задача пришла текстом — прогонять нечего. Тогда прочитай постановку сам и скажи строкой, что готовность машиной не проверялась; работу при этом не останавливай. -## Две ветки +## Развилка: какой сценарий -Развилка одна и стоит на входе: +Она одна, и стоит до всякой работы: **есть ли у задачи один очевидный способ +решения?** -- **обычная задача** — что делать, понятно; спорно только как. Идёт с шага 1; -- **исследовательская** — тип `research`, сырая идея, новое и незнакомое, мутная - постановка. Идёт с шага Р1, и там её ждёт **свой** чекпоинт: варианты решения - обсуждаются **до** того, как написано первое требование. +- **есть** — что делать, понятно; спорно только как. **Сценарий решения** — + [references/solve.md](references/solve.md); +- **нет** — тип `research`, сырая идея, новое и незнакомое, мутная постановка, + два подхода с разной ценой. **Сценарий разведки** — + [references/research.md](references/research.md). -Признак не в объёме работы, а в том, **есть ли у задачи один очевидный способ -решения**. Его нет — обсуждать варианты после `propose` поздно: предложение уже -воплотило один из них, и разговор пойдёт не о выборе, а о переделке. +Признак не в объёме работы. Крупная задача с очевидным способом идёт в решение; +маленькая, но незнакомая — в разведку. Тип `research` в разведку идёт всегда: её +исход знание, а не изменение системы. + +**Назови выбранный сценарий вслух первой репликой** — одной строкой, с причиной. +Молча выбранный сценарий человек обнаруживает по тому, что работа пошла не туда, +и обнаруживает поздно. + +### Сценарий выбирается один раз + +**Смена сценария по ходу — событие, а не тихий поворот**, и каждая из двух смен +устроена по-своему: + +- **решение → разведка**: обнаружилось, что очевидного способа нет. Это **стоп** + с исходом «нужна разведка»: назови, что именно неясно, и не продолжай. + Кода к этому моменту не написано, и писать его «пока разбираемся» нельзя; +- **разведка → решение**: способ выбран на чекпоинте вариантов. Разведка **всё + равно доводится до конца** — ответ записан, задачи уточнены, коммит сделан, — + и решение идёт **следующим прогоном**, который запускает человек. + +**Соблазн «разведаю по ходу» живёт именно здесь**, и он дорог тем, что выглядит +экономией одного прогона. Разведка внутри решения не имеет своего чекпоинта: +выбор делается тем, кто уже начал писать, и человек видит его только в +объяснении, где обсуждать выбор поздно. Ровно за это сценарии и разведены — не за +то, что это разные работы, а за то, что у них разные моменты для человека. ```mermaid flowchart TD in["вход: файл, слаг или текст"] + ready["ready: готовность записи
av-dev-tasks:tasks"] fork{"есть очевидный
способ решения?"} - r1["Р1. понять вопрос
сырьё без «Вопроса» — отказ"] - r2["Р2. opsx:explore — груминг"] - r3(["Р3. ЧЕКПОИНТ: варианты
2–4 способа, цена каждого,
рекомендация"]) - rout["исход без кода:
ответ записан / отказ / родились задачи"] - s1["1. прочитать задачу
критерии приёмки выписать сразу"] - s2["2. opsx:propose — change, дельта-спеки, tasks.md"] - s3["3. разметка — review-scope:
размер, сложность, метка, план тем"] - s4["4. ревью дизайна, состав по метке
+ отработка замечаний"] - s5(["5. ЧЕКПОИНТ: объяснение
в чём проблема, как решаем,
чем рискуем"]) - s6["6. opsx:apply — код, гейт,
поведенческая верификация"] - s7["7. ревью кода, та же метка
+ отработка замечаний"] - s8["8. opsx:archive"] - s9["9. синк документации — av-dev-docs:docs"] - s10["10. коммит работы — av-dev-git:commit"] - s11["11. закрыть задачу — av-dev-tasks:tasks,
вторым коммитом учёта"] + solve["сценарий решения
references/solve.md
код, ревью, архив, коммит"] + res["сценарий разведки
references/research.md
ответ в документы и задачи"] - in --> fork - fork -->|"да"| s1 - fork -->|"нет"| r1 - r1 --> r2 --> r3 - r3 -->|"выбран способ"| s1 - r3 -.->|"кода не будет"| rout - s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 --> s11 - s3 -.->|"план задачи: та же метка"| s7 - s5 -.->|"скорректировать:
меняются дельта-спеки"| s3 - s7 -.->|"находка отменяет дизайн:
меняются дельта-спеки"| s3 + in --> ready --> fork + fork -->|"да"| solve + fork -->|"нет"| res + solve -.->|"способа всё же нет:
стоп, кода не написано"| res + res -.->|"способ выбран:
следующим прогоном,
зовёт человек"| solve ``` -Схема — **сводка**: содержание каждого шага в его разделе ниже, и при -расхождении прав текст. +Схема — **сводка**: содержание сценариев в их справочниках, и при расхождении +прав справочник. -## Автономность и два плановых стопа +## Автономность и плановый стоп -**Между чекпоинтами умолчание прежнее — делать, а не спрашивать.** Чекпоинты не -отменяют автономность, они дают развилкам плановое место, куда копиться. +**У каждого сценария ровно один плановый стоп**, и стоят они в разных местах: +у решения — объяснение после ревью дизайна, у разведки — варианты до первого +написанного требования. Правило вокруг них общее. + +**Вокруг чекпоинта умолчание прежнее — делать, а не спрашивать.** Чекпоинт не +отменяет автономность, он даёт развилкам плановое место, куда копиться. Разрез простой: -- развилка найдена **до** ближайшего чекпоинта — она его и ждёт. Не спрашивай - отдельно: чекпоинт рядом и стоит дёшево, а три вопроса подряд стоят дороже - одного разговора; -- развилка найдена **после** последнего чекпоинта — старое правило: **запиши - вопрос и доведи остаток**, не останавливаясь. +- развилка найдена **до** чекпоинта — она его и ждёт. Не спрашивай отдельно: + чекпоинт рядом и стоит дёшево, а три вопроса подряд стоят дороже одного + разговора; +- развилка найдена **после** чекпоинта — старое правило: **запиши вопрос и доведи + остаток**, не останавливаясь. Запись вопроса устроена так: @@ -171,7 +197,8 @@ flowchart TD 2. **Переформулируй задачу на остаток** — то, что делается без этого решения. Назови границу: докуда доводим сейчас. 3. Доведи остаток до конца и закоммить. Задача не «висит на вопросе», она сделана - в объявленных границах. + в объявленных границах. В разведке остаток — это ответ в объявленных рамках: + что успели узнать, где остановились и почему. **Что остатком не является — правило живёт не здесь.** Канонический текст с обеими оговорками — в плагине `av-dev-tasks`, скилл `av-dev-tasks:groom`, раздел @@ -194,7 +221,7 @@ flowchart TD Нет полезного остатка — задача заканчивается исходом «не доведена», вопрос записан, ничего не коммитится наполовину. -### Когда спрашивать вне чекпоинтов +### Когда спрашивать вне чекпоинта По другому основанию — не «сложное решение», а **необратимое действие**: @@ -205,453 +232,60 @@ flowchart TD Здесь ошибка не откатывается коммитом, поэтому спрашиваем даже когда решение кажется очевидным. -Стиль правок — заточка под проект и конвенции, right-size, без золочения. - ## Границы: чем этот скилл не владеет - **Беклогом, целями и приоритетами.** Задача приходит извне. Скилл её не выбирает, не приоритизирует, не заводит и не переоценивает. -- **Форматом задач.** Индексы руками не правятся, путь к скрипту учёта не - выдумывается: этим владеет `av-dev-tasks:tasks` (шаг 11). Закрытие — работа - этого скилла, и это осознанное решение с названной ценой: **приёмщик и - исполнитель совпали**. Закрытие поэтому **не окончательно** — человек на +- **Форматом задач и документов.** Индексы и документы канона руками не правятся, + путь к чужому скрипту не выдумывается: этим владеют `av-dev-tasks:tasks` и + `av-dev-docs:docs`. Закрытие — работа этого скилла, и это осознанное решение с + названной ценой: **приёмщик и исполнитель совпали**. Закрытие поэтому **не окончательно** — человек на груминге (`av-dev-tasks:groom`) возвращает задачу `reopen` с причиной, а доклад по критериям приёмки становится единственным, по чему приёмка вообще возможна. -- **Заведением задач из урожая ревью.** Отложенные находки отдаются **списком**; - превращать их в задачи — работа `av-dev-tasks:tasks`, у него на этот вход - отдельный сценарий «задачи из ревью и аудита». Плагина нет — урожай остаётся - списком в докладе, и это говорится строкой. - **Определением ценности.** «Нужна ли эта функциональность» — не вопрос этого - скилла ни на одном шаге. Чекпоинт спрашивает «так ли решаем», а не «надо ли». + скилла ни на одном шаге и ни в одном сценарии. Чекпоинт решения спрашивает «так + ли решаем», чекпоинт разведки — «каким из способов», но не «надо ли». + +Что не принадлежит **отдельному сценарию**, названо у него же: урожай ревью и +выбор способа — в [solve.md](references/solve.md), код и приоритет — в +[research.md](references/research.md). ## Наблюдаемые исходы -Ровно четыре, и каждый обязан быть назван в докладе прямо: - -- **сделана** — определение сделанного выполнено целиком; -- **не доведена** — с причиной и с записанным вопросом; что именно сделано и до - какой границы, названо явно. Сюда же попадает чекпоинт, на котором человек - решение не одобрил; -- **оказалась крупнее задачи** — распознаётся **до заведения change**, иначе его - придётся выбрасывать. Дальше — декомпозиция, и это не работа этого скилла; -- **знание вместо изменения** — только у исследовательской ветки: ответ записан - по названному адресу, кода задача не потребовала. Это полноправный исход, а не - недоведённая работа. - -## Определение сделанного - -Задача сделана, когда верно всё: - -1. гейт проекта зелёный; -2. ревью проведено, **план прогона сверен с исходом по каждой теме**, темы без - отчёта и без дома названы в границах покрытия; -3. решение прошло чекпоинт и не разошлось с одобренным — либо разошлось, и - чекпоинт был пройден заново; -4. change заархивирован, дельты влиты в актуальные спеки; -5. коммит сделан в текущую ветку; -6. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван - оракул и наблюдаемый исход** — «прогнал вот это, увидел вот то». Это **доклад, - а не сертификация: приёмка — не работа этого скилла.** Исполнитель, ставящий - себе галочку «принято», проверяет свою работу своим же взглядом — по границе - это может делать только приёмщик, разведённый с исполнителем. Критерии приходят - снаружи; скилл их не сочиняет и не занижает. Расхождение «по каждому критерию - исход есть, а суть задачи не достигнута» — дефект критериев, и о нём - сообщается, а не молча дорабатывается. - -У разведки, кончившейся знанием, определение своё и короткое: **ответ записан по -адресу, который назвала задача**, и в нём есть провенанс у каждого числа. - -## Исследовательская ветка - -### Р1. Понять вопрос - -Прочитай запись. У типа `research` в ней два обязательных раздела, и оба нужны -тебе прямо сейчас: **«Вопрос»** — на что отвечаем, **«Куда ляжет ответ»** — по -какому адресу он ляжет. Адрес назван заранее не из аккуратности: ответ, не -имеющий дома, остаётся в переписке, и через квартал разведку заказывают заново. - -Вопроса нет — исход «не доведена» с причиной «запись это сырьё»: назови, что -нужно дописать, и остановись. Адреса нет, а вопрос есть — назначь адрес сам и -скажи об этом строкой: разведка без дома для ответа хуже несделанной. - -Задача не из каталога (пришла текстом) — адреса у неё нет по построению. Тогда -дом ответа — `design.md` того change, который родится дальше; кода не будет — -`docs/research/`, и это тоже говорится строкой. - -### Р2. Груминг — `opsx:explore` - -Вызови Skill `opsx:explore`. Читай документы проекта, а не только запись: -граница домена и «чем проект **не** является» из паспорта отсекают половину -вариантов до того, как их начнут сравнивать. **В explore не пишем код.** - -Развилку грумминга **не записывай вопросом** — она и есть предмет следующего -шага. Это отличие от обычной ветки: там развилка уходит в запись, здесь она -копится в чекпоинт. - -### Р3. Чекпоинт: варианты - -**Остановись и покажи человеку способы решить.** Это первый из двух плановых -стопов, и он существует потому, что после `propose` выбор уже сделан -предложением. - -Форма — короткая, экран текста: - -- **вопрос**, на который отвечаем, одной фразой (он уже есть в записи); -- **2–4 варианта**, не больше. Больше четырёх — это не выбор, а список: человек - не сравнит, а признает свою неспособность сравнить и попросит рекомендацию. - У каждого варианта: в чём суть простыми словами, **что даёт**, **чего стоит**, - **что становится невозможным** (это ловится хуже всего и стоит дороже всего); -- **рекомендация с причиной**. Человек чаще соглашается, чем выбирает заново; -- что известно **недостоверно** и как это проверить, если проверять дёшево. - -Что нельзя: приносить варианты, различающиеся только реализацией; прятать -отвергнутое (отвергнутый вариант с названной причиной — половина будущего ADR); -приносить один вариант и называть это выбором. - -**Выбор оседает по адресу.** У `research` это раздел «Куда ляжет ответ». У -остальных — `design.md` change, который родится на шаге 2, разделом -«рассмотренные варианты». Не в переписку: разговор, из которого ничего не -записано, повторяется через месяц целиком. - -Три исхода чекпоинта: - -- **выбран способ** — идёшь на шаг 1 общей ветки; -- **ответ и есть исход** — работа кончается знанием: запиши ответ по адресу, - доложи исход «знание вместо изменения» и закрой задачу (шаг 11). Провенанс у - каждого числа обязателен: число без источника проход ревью обязан читать как - условие, а не как замер; -- **разведка родила задачи** — исход «оказалась крупнее задачи». Нарезка не твоя - работа: отдай список формулировками и остановись. - -## Шаги - -### 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 `. - -Критерии приёмки задачи, если они были, копируются в `tasks.md` отдельным блоком. -Варианты, разобранные на чекпоинте Р3, — в `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 ``, -**план разметки с шага 3** и указание, что это ревью дизайна. - -Состав приходит планом, а не решается здесь: - -| Метка | Проходы на предложении | -|---|---| -| `small` | `specs` | -| `medium` | `specs`, `rubric` | -| `large` | `specs`, `rubric`, `architecture` + вопрос автору о трёх формах решения | - -`review-specs` в режиме «дизайн ДО кода» идёт **на каждой задаче**: это самый -дешёвый проход конвейера, и он ловит то, что на готовом коде уже не чинят. -Остальные включаются меткой, потому что стадия стоит на каждой задаче и каждый -лишний проход здесь умножается на число задач. - -Смысл стадии: архитектурная находка на готовом коде стоит переписывания и потому -игнорируется — та же находка здесь стоит абзаца обсуждения. Если `review-rubric` -запускался, перенеси его рубрику в `tasks.md` как приёмочные критерии; там же уже -лежат критерии от постановки, если они были. - -**Отработка замечаний, и она идёт до чекпоинта, а не после:** - -- мелочь и явные улучшения — правь сам в спеках и дизайне; -- развилки (компромисс, scope, инвариант) — **не в запись, а в чекпоинт**: он - следующим шагом, и это ровно то, ради чего он поставлен здесь; -- после правок перепрогони `openspec validate --strict `. - -### 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 ``, -базу диффа, **план разметки с шага 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//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 показывают, что и -когда закрыто» без коммита — пустые слова. Сообщение короткое, про учёт, а не про -работу: `закрыта задача `. Это второй коммит осознанно: правило «одна задача -— один осмысленный коммит» про работу, а учёт — не работа. - -Разведка, кончившаяся знанием, закрывается так же — но перед этим убедись, что -ответ **записан по названному адресу и закоммичен**. Закрытая разведка без -записанного ответа не оставляет следа вообще: файл задачи удалён, ответ был в -переписке. - -Плагина в проекте нет — вызов не разрешится. Тогда **ничего не выдумывай**: скажи -в докладе, что учёт задач остаётся за владельцем, и назови исход. +**У каждого сценария их четыре**, и живут они у сценария: +[решение](references/solve.md) — сделана, не доведена, оказалась крупнее задачи, +нужна разведка; [разведка](references/research.md) — способ выбран, знание +записано, отказ, не доведена. + +Общего исхода нет намеренно. «Сделана» у решения и «знание записано» у разведки — +разные вещи с разной приёмкой, и слово, накрывающее оба, скрывало бы именно то, +чем прогон кончился. ## Доклад -Коротко, и в нём обязательно: +Ядро общее, и в нём обязательно: -- **исход** одним из четырёх слов и, если не «сделана», чем ограничен результат; +- **какой сценарий шёл** — решение или разведка, — и почему выбран он; +- **исход** одним из четырёх слов своего сценария и, если он не благополучный, + чем ограничен результат; - что сделано, какие вопросы записаны и куда; -- **что было одобрено на чекпоинте и совпало ли с тем, что уехало в коммит** — - расхождение здесь называется прямо, даже если оно мелкое; -- ссылка на архивный change и хеш коммита; -- по каждому критерию приёмки, если они были: **оракул и наблюдаемый исход** — - это доклад приёмщику, а не отметка «принято»; -- **`Урожай`** — отложенные находки списком (формулировка, оракул, провенанс); -- **одна строка границ покрытия**: какая метка и режим гонялись, какие проходы не - запускались и что проверить было невозможно. Доклад без неё сообщает - «проверено», не сообщая, что именно. +- чего проверить или узнать **не удалось**. + +Сверх ядра каждый сценарий добавляет своё: [solve.md](references/solve.md) — +чекпоинт, change, критерии приёмки, урожай и границы покрытия; +[research.md](references/research.md) — вопрос и ответ, адреса записи, заведённые +задачи, рамки. ## Тонкости - **Не завязывайся на основную ветку и корень репозитория.** Скилл работает в текущем worktree и на текущей ветке: не делай `git checkout`/`switch`, не создавай веток, не пушь. -- Обычная задача с очевидным решением проходит **один** чекпоинт, и это норма, а - не упрощение. Два чекпоинта — цена незнания, а не признак серьёзности задачи. -- Гейт блокирует: пока он красный, опиниативные проходы не запускаются. Чинить и - перезапускать, а не «посмотреть заодно». +- Прогон проходит **один** чекпоинт, и это норма, а не упрощение. Два стопа за + одну задачу — цена незнания способа, и платится она двумя прогонами, а не одним + длинным. - Держи вызывающего в цикле короткими репликами на переходах фаз, но не проси - подтверждать механику: чекпоинты — единственные места, где ждут ответа. -- **Занизить метку ревью, пропустить тему или проскочить чекпоинт — самый дешёвый - способ «ускориться», и он же самый дорогой по последствиям.** Защита устроена - так, что регулятора у тебя нет: метку выбирает разметчик **до того**, как ты - написал код, план сверяется по темам, непокрытое называется строкой, а - расхождение с одобренным — отдельным пунктом доклада. + подтверждать механику: чекпоинт — единственное место, где ждут ответа. +- **Сценарий назван вслух — значит, его можно оспорить.** Человек, увидевший в + первой реплике «иду разведкой, потому что способа не видно», поправит выбор + одной фразой; молча выбранный сценарий он поправит через полчаса работы. diff --git a/av-dev-code/skills/resolve/references/research.md b/av-dev-code/skills/resolve/references/research.md new file mode 100644 index 0000000..f0cd301 --- /dev/null +++ b/av-dev-code/skills/resolve/references/research.md @@ -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. вопрос и рамки
сырьё без «Вопроса» — отказ"] + s2["2. разведка: документы, код,
внешние источники, opsx:explore"] + s3(["3. ЧЕКПОИНТ: варианты
2–4 способа, цена каждого,
что становится невозможным"]) + s4["4. ответ в документы канона
av-dev-docs:docs"] + s5["5. задачи: завести и уточнить
av-dev-tasks:tasks"] + s6["6. гейт проекта, затем коммит
av-dev-git:commit"] + s7["7. закрыть разведку — av-dev-tasks:tasks,
вторым коммитом учёта"] + out["исход назван: знание, задачи,
отказ или «не доведена»"] + + in --> s1 --> s2 --> s3 + s3 -->|"выбран способ,
отказ или знание"| 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 упадёт. У +разведки это опаснее, чем у решения: следом работы там служит код, а здесь — +только записанный ответ. Закрытая разведка без него не оставляет следа вообще — +файл задачи удалён, ответ был в переписке. + +**Закрытие тоже коммитится — вторым коммитом, тут же.** Сообщение короткое, про +учёт, а не про работу: `закрыта задача `. Правило «одна разведка — один +коммит» про работу, а учёт — не работа. + +Плагина в проекте нет — **ничего не выдумывай**: скажи в докладе, что учёт задач +остаётся за владельцем, и назови исход. + +## Доклад разведки + +Общая форма доклада — в SKILL.md; у разведки он свой, потому что докладывать +нечего из того, о чём спрашивают решение (ни метки ревью, ни критериев приёмки, +ни архивного change). Коротко, и в нём обязательно: + +- **исход** одним из четырёх слов; +- **вопрос и ответ** — по фразе на каждое. Ответ, который не сворачивается во + фразу, — признак того, что разведка отвечала не на один вопрос; +- **куда записано** — перечнем адресов, а не «документация обновлена»; +- **какие задачи заведены и уточнены** — слагами; +- **что осталось неизвестным** и чего это стоит: разведка без этой строки + сообщает «выяснено», не сообщая, что именно осталось не выяснено; +- **рамки**, если они ограничили работу: докуда копали и почему остановились. + +## Тонкости + +- **Ответ «зависит от» — не ответ.** Если разведка кончилась развилкой, её исход + — варианты с ценой, а не пересказ обеих сторон без рекомендации. +- **Отрицательный результат записывается так же тщательно, как положительный.** + Соблазн не писать его велик: кажется, что писать нечего. Через квартал именно + этой записи и не хватит. +- **Чужую разведку не переоткрывай молча.** Нашёл в `docs/research/` или в + `docs/adr/` ответ на свой вопрос — исход «знание записано» со ссылкой, и это + лучшая из возможных разведок: она стоила одного чтения. diff --git a/av-dev-code/skills/resolve/references/solve.md b/av-dev-code/skills/resolve/references/solve.md new file mode 100644 index 0000000..7e5977a --- /dev/null +++ b/av-dev-code/skills/resolve/references/solve.md @@ -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. прочитать задачу
критерии приёмки выписать сразу"] + s2["2. opsx:propose — change, дельта-спеки, tasks.md"] + s3["3. разметка — review-scope:
размер, сложность, метка, план тем"] + s4["4. ревью дизайна, состав по метке
+ отработка замечаний"] + s5(["5. ЧЕКПОИНТ: объяснение
в чём проблема, как решаем,
чем рискуем"]) + s6["6. opsx:apply — код, гейт,
поведенческая верификация"] + s7["7. ревью кода, та же метка
+ отработка замечаний"] + s8["8. opsx:archive"] + s9["9. синк документации — av-dev-docs:docs"] + s10["10. коммит работы — av-dev-git:commit"] + s11["11. закрыть задачу — av-dev-tasks:tasks,
вторым коммитом учёта"] + + in --> s1 + s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 --> s11 + s3 -.->|"план задачи: та же метка"| s7 + s5 -.->|"скорректировать:
меняются дельта-спеки"| s3 + s7 -.->|"находка отменяет дизайн:
меняются дельта-спеки"| 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 `. + +Критерии приёмки задачи, если они были, копируются в `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 ``, +**план разметки с шага 3** и указание, что это ревью дизайна. + +Состав приходит планом, а не решается здесь: + +| Метка | Проходы на предложении | +|---|---| +| `small` | `specs` | +| `medium` | `specs`, `rubric` | +| `large` | `specs`, `rubric`, `architecture` + вопрос автору о трёх формах решения | + +`review-specs` в режиме «дизайн ДО кода» идёт **на каждой задаче**: это самый +дешёвый проход конвейера, и он ловит то, что на готовом коде уже не чинят. +Остальные включаются меткой, потому что стадия стоит на каждой задаче и каждый +лишний проход здесь умножается на число задач. + +Смысл стадии: архитектурная находка на готовом коде стоит переписывания и потому +игнорируется — та же находка здесь стоит абзаца обсуждения. Если `review-rubric` +запускался, перенеси его рубрику в `tasks.md` как приёмочные критерии; там же уже +лежат критерии от постановки, если они были. + +**Отработка замечаний, и она идёт до чекпоинта, а не после:** + +- мелочь и явные улучшения — правь сам в спеках и дизайне; +- развилки (компромисс, scope, инвариант) — **не в запись, а в чекпоинт**: он + следующим шагом, и это ровно то, ради чего он поставлен здесь; +- после правок перепрогони `openspec validate --strict `. + +### 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 ``, +базу диффа, **план разметки с шага 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//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 показывают, что и +когда закрыто» без коммита — пустые слова. Сообщение короткое, про учёт, а не про +работу: `закрыта задача `. Это второй коммит осознанно: правило «одна задача +— один осмысленный коммит» про работу, а учёт — не работа. + +Плагина в проекте нет — вызов не разрешится. Тогда **ничего не выдумывай**: скажи +в докладе, что учёт задач остаётся за владельцем, и назови исход. + +## Доклад решения + +Общее ядро доклада — в SKILL.md; сверх него сценарий решения обязан назвать: + +- **что было одобрено на чекпоинте и совпало ли с тем, что уехало в коммит** — + расхождение здесь называется прямо, даже если оно мелкое; +- ссылка на архивный change и хеш коммита; +- по каждому критерию приёмки, если они были: **оракул и наблюдаемый исход** — + это доклад приёмщику, а не отметка «принято»; +- **`Урожай`** — отложенные находки списком (формулировка, оракул, провенанс); +- **одна строка границ покрытия**: какая метка и режим гонялись, какие проходы не + запускались и что проверить было невозможно. Доклад без неё сообщает + «проверено», не сообщая, что именно. + +## Тонкости сценария + +- Гейт блокирует: пока он красный, опиниативные проходы не запускаются. Чинить и + перезапускать, а не «посмотреть заодно». +- Стиль правок — заточка под проект и конвенции, right-size, без золочения. +- **Занизить метку ревью, пропустить тему или проскочить чекпоинт — самый дешёвый + способ «ускориться», и он же самый дорогой по последствиям.** Защита устроена + так, что регулятора у тебя нет: метку выбирает разметчик **до того**, как ты + написал код, план сверяется по темам, непокрытое называется строкой, а + расхождение с одобренным — отдельным пунктом доклада. +- **Заведение задач из урожая ревью — не твоя работа.** Отложенные находки + отдаются **списком**; превращает их в задачи `av-dev-tasks:tasks`, у него на + этот вход отдельный сценарий «задачи из ревью и аудита». Плагина нет — урожай + остаётся списком в докладе, и это говорится строкой. +- **Способ решения ты не выбираешь.** Он приходит известным: из постановки, из + разведки, от человека. Выбор между двумя подходами с разной ценой делается в + разведке, у своего чекпоинта, — не по ходу этого сценария. diff --git a/av-dev-docs/agents/doc-consistency.md b/av-dev-docs/agents/doc-consistency.md index d77a26e..7cb1d06 100644 --- a/av-dev-docs/agents/doc-consistency.md +++ b/av-dev-docs/agents/doc-consistency.md @@ -1,6 +1,6 @@ --- name: doc-consistency -description: "Сверка документов канона между собой и с openspec: один факт, живущий в двух домах, прямое противоречие между документами (периметр, зависимости, обратимость), поведение системы, осевшее в architecture.md вместо спек, capability без обзора или с пересказом требований, число без провенанса в research, ADR без ссылки на архивный design.md и без парного статуса при замене, заглушка вместо честной строки в пустом слоте. Читает docs/ и openspec/, кода не читает. Отдаёт готовые формулировки и ничего не правит сам. Соответствие документов коду смотрит агент doc-code-drift, язык — doc-wording. Зовётся скиллом av-dev-docs:healthcheck — на весь канон разом; он же зовётся шагом adopt и шагом upgrade. На отдельной задаче и на синке документации не звать. Только чтение." +description: "Сверка документов канона между собой и с openspec: один факт, живущий в двух домах, прямое противоречие между документами (периметр, зависимости, обратимость), поведение системы, осевшее в architecture.md вместо спек, capability без обзора или с пересказом требований, число без провенанса в research, ADR без ссылки на источник (архивный design.md либо записка разведки) и без парного статуса при замене, заглушка вместо честной строки в пустом слоте. Читает docs/ и openspec/, кода не читает. Отдаёт готовые формулировки и ничего не правит сам. Соответствие документов коду смотрит агент doc-code-drift, язык — doc-wording. Зовётся скиллом av-dev-docs:healthcheck — на весь канон разом; он же зовётся шагом adopt и шагом upgrade. На отдельной задаче и на синке документации не звать. Только чтение." tools: Read, Grep, Glob model: opus color: yellow @@ -23,7 +23,7 @@ color: yellow | Факт | Дом | | --- | --- | | поведение системы | `openspec/specs//spec.md` | -| почему решено так | `adr/`, источник — архивный `design.md` | +| почему решено так | `adr/`, источник — архивный `design.md` либо записка разведки | | граница домена, «чем не является» | `passport.md` | | инвариант и его severity | `CLAUDE.md` | | что приложение умеет и чего не умеет; порядок работ | `tasks/ROADMAP.md` | @@ -50,7 +50,10 @@ color: yellow `docs/tasks/` на непереехавшем проекте), принадлежит другому плагину и ведётся своим скриптом; не открывай его ни в той форме, ни в другой. Плюс `openspec/changes/archive/`, когда проверяешь ADR: там лежат `design.md`, из -которых записи промоутятся. +которых записи промоутятся. **Источник у ADR бывает и второй — записка +разведки**: решение, принятое без изменения (намеренный отказ, выбор подхода), +`design.md` не имеет по построению. Запись без ссылки **на любой из двух** — +находка; запись со ссылкой на записку — нет. **Кода ты не читаешь.** Разошёлся ли документ с кодом — вопрос агента `doc-code-drift`, и у него для этого другой вход и другая цена. diff --git a/av-dev-docs/skills/canon/references/canon.md b/av-dev-docs/skills/canon/references/canon.md index f5c243d..33f06c1 100644 --- a/av-dev-docs/skills/canon/references/canon.md +++ b/av-dev-docs/skills/canon/references/canon.md @@ -1,6 +1,10 @@ # Канон документов проекта -**Версия 12.** +**Номер версии здесь не стоит намеренно.** Этот файл описывает канон таким, какой +он сейчас, а число живёт в двух домах, которые не расходятся: константа в +`docs.py` (её печатает `docs.py version`) и верхняя запись +[журнала](changelog.md). Литерал в шапке был третьим и отстал на первом же +повышении — версию 13 он пережил, объявляя канон двенадцатым. Это **единственный дом определения канона**. Скиллы `init`, `canon` и `docs` читают его, а не пересказывают: три описания одной раскладки разъедутся, и @@ -141,7 +145,7 @@ openspec/ **Процессный документ — не документ второго сорта.** `adr/` и `research/` проверяются наравне с остальными, но **сверкой документации**, а не прогоном -ревью: ADR без ссылки на архивный `design.md`, замена без парного статуса, число +ревью: ADR без ссылки на источник, замена без парного статуса, число без провенанса — это работа агентов `doc-consistency` и `doc-code-drift`, и она осталась там же, где была. Изменилось одно: прогон ревью не открывает их как критерий и не судит по ним изменение. @@ -291,8 +295,17 @@ kebab-case.** Причина не эстетическая: имя файла с ### `adr/` -**ADR — промоут поверх архивных `design.md`, а не второе сочинение.** Запись -цитирует решение и ссылается на `openspec/changes/archive//design.md`. +**ADR — промоут поверх уже написанного, а не второе сочинение.** Запись цитирует +решение и ссылается на источник. Источников два, и оба законны: + +- **архивный `design.md`** — решение принято по ходу изменения: + `openspec/changes/archive//design.md`. Обычный случай; +- **записка разведки** — решение принято разведкой, и change по нему не будет + никогда: намеренный отказ, выбор подхода, «проверили и не делаем». У такой + работы нет `design.md` по построению, и без второго источника её решение либо + не попадало в `adr/` вовсе, либо попадало сочинённым заново. + +Источник называется в записи всегда — по нему видно, чем решение подтверждено. Заводится, когда верно одно из трёх: @@ -458,7 +471,7 @@ kebab-case.** Причина не эстетическая: имя файла с | Факт | Дом | | --- | --- | | поведение системы | `openspec/specs//spec.md` | -| почему решено так | `adr/`, источник — архивный `design.md` | +| почему решено так | `adr/`, источник — архивный `design.md` либо записка разведки | | граница домена, «чем не является» | `passport.md` | | инвариант и его severity | `CLAUDE.md` | | что приложение умеет и чего не умеет; порядок работ | `tasks/ROADMAP.md` | @@ -513,7 +526,7 @@ kebab-case.** Причина не эстетическая: имя файла с | имя файла не kebab-case латиницей; форма имени ADR | транслит в имени — сверх эвристики | `doc-wording` | | битые относительные ссылки | прямое противоречие между документами | `doc-consistency` | | версия канона и её отставание | достаточность честной строки в пустом слоте | `doc-consistency` | -| нетронутый плейсхолдер шаблона | ADR без ссылки на `design.md`, замена без парного статуса | `doc-consistency` | +| нетронутый плейсхолдер шаблона | ADR без ссылки на источник, замена без парного статуса | `doc-consistency` | | маркеры долга — числом | **протухший факт, разошедшийся с кодом** | `doc-code-drift` | | миграция изменена, а `database.md` нет | зависимость в манифесте, не названная в обзоре | `doc-code-drift` | | capability без упоминания в `architecture.md` | второй способ там, где обзор обещал единственный | `doc-code-drift` | diff --git a/av-dev-docs/skills/canon/references/changelog.md b/av-dev-docs/skills/canon/references/changelog.md index f222b08..069cdc9 100644 --- a/av-dev-docs/skills/canon/references/changelog.md +++ b/av-dev-docs/skills/canon/references/changelog.md @@ -20,6 +20,44 @@ upgrade` идёт по записям снизу вверх от версии п --- +## Версия 14 — 2026-08-11 + +У ADR стало два законных источника. Прежде запись цитировала только архивный +`design.md`, то есть решение, принятое по ходу изменения. Решение, принятое +**разведкой** — намеренный отказ, выбор подхода, «проверили и не делаем», — не +имеет `design.md` по построению: change по нему не заводится никогда. Триггер +канона такое решение ловит («намеренный отказ от очевидного подхода»), а дома у +него не было, и оно оседало в записке разведки или в переписке. + +**Что изменилось.** `adr/` принимает второй источник — записку разведки. Правило +«промоут, а не второе сочинение» не тронуто: запись по-прежнему цитирует уже +написанное и **называет источник**, изменилось только то, что источников два. +Следом сказали то же самое: карта домов, разрез проверки `doc-consistency`, вход +и устав самого агента, скелеты `docs/adr/README.md` и `docs/adr/template.md`. + +**Почему это версия, а не правка текста.** Два следствия уезжают в репозиторий +проекта. По карте домов судит агент согласованности — прежняя редакция читала ADR +со ссылкой на записку разведки как нарушение; а скелеты `adr/` лежат в проекте +файлами и говорят там от имени канона. + +**Что сделать проекту.** + +1. Ничего с существующими записями: прежние ADR ссылаются на `design.md`, и это + по-прежнему верно. +2. **Поднять шапку `docs/adr/README.md`**: «промоут поверх архивного `design.md`» + → «промоут поверх уже написанного», с обоими источниками. Точный текст — в + [skeletons.md](skeletons.md), раздел `docs/adr/README.md`. +3. **Поднять `docs/adr/template.md`**: строка `- **Источник:**` называет два + возможных источника. +4. `docs/.docs.json`: `"canon": 14`. + +**Чего делать не надо.** Заводить ADR задним числом по старым разведкам. Запись +заводится, когда решение принимается, а не когда о нём вспомнили: сочинённое +через полгода обоснование — ровно то «второе сочинение», против которого правило +и написано. + +--- + ## Версия 13 — 2026-08-11 Служебный файл канона переименован: `docs/.pm.json` → `docs/.docs.json`. Имя diff --git a/av-dev-docs/skills/canon/references/skeletons.md b/av-dev-docs/skills/canon/references/skeletons.md index f4a837f..274514d 100644 --- a/av-dev-docs/skills/canon/references/skeletons.md +++ b/av-dev-docs/skills/canon/references/skeletons.md @@ -200,9 +200,10 @@ ```markdown # Журнал решений -Одна запись — одно решение. **ADR это промоут поверх архивного `design.md`**, -а не второе сочинение: запись цитирует решение и ссылается на -`openspec/changes/archive//design.md`. +Одна запись — одно решение. **ADR это промоут поверх уже написанного**, а не +второе сочинение: запись цитирует решение и ссылается на источник — +`openspec/changes/archive//design.md`, а у решения, принятого разведкой без +изменения, на её записку. ## Когда заводить @@ -241,7 +242,8 @@ # Краткий заголовок решения - **Дата:** ГГГГ-ММ-ДД -- **Источник:** openspec/changes/archive//design.md +- **Источник:** openspec/changes/archive//design.md — либо записка разведки, + если решение принято без изменения Статус ставится тем же полем и только при пересмотре: `- **Статус:** заменено на ADR-…` либо `- **Статус:** устарело`. diff --git a/av-dev-docs/skills/canon/scripts/docs.py b/av-dev-docs/skills/canon/scripts/docs.py index 4c6e72c..ddcfa73 100644 --- a/av-dev-docs/skills/canon/scripts/docs.py +++ b/av-dev-docs/skills/canon/scripts/docs.py @@ -25,7 +25,7 @@ from dataclasses import dataclass, field from pathlib import Path from typing import NoReturn -CANON_VERSION = 13 +CANON_VERSION = 14 OK, DRIFT, USAGE, ENV, INTERNAL = 0, 1, 2, 3, 4 diff --git a/av-dev-docs/skills/docs/SKILL.md b/av-dev-docs/skills/docs/SKILL.md index 428d9d3..073eccd 100644 --- a/av-dev-docs/skills/docs/SKILL.md +++ b/av-dev-docs/skills/docs/SKILL.md @@ -1,6 +1,6 @@ --- name: docs -description: Вести содержимое документов канона по ходу разработки — синк после сделанной задачи с построчным отчётом по каждому документу, заведение ADR промоутом из архивного design.md, запись наблюдения в research, запись дефекта и настройки конвейера в review.md, чистка architecture.md от поведения с маркерами долга. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл canon. +description: Вести содержимое документов канона по ходу разработки — синк после сделанной задачи с построчным отчётом по каждому документу, заведение ADR промоутом из архивного design.md или из записки разведки, запись наблюдения в research, запись дефекта и настройки конвейера в review.md, чистка architecture.md от поведения с маркерами долга. Использовать, когда задача сделана и надо обновить документацию, когда просят завести ADR или записать решение, занести находку о внешних данных, записать проскочивший дефект, разгрузить разросшуюся архитектуру. Раскладку и соответствие канону проверяет скилл canon. --- # Ведение содержимого канона @@ -97,6 +97,13 @@ description: Вести содержимое документов канона **ADR цитирует решение оттуда и ссылается на источник.** Не пересказывает и не сочиняет заново. +**Второй законный источник — записка разведки**, и приходит он от скилла +`av-dev-code:research`: решение, принятое разведкой (намеренный отказ, выбор +подхода, «проверили и не делаем»), `design.md` не имеет по построению — change по +нему не будет никогда. Промоут при этом тот же: цитата и ссылка, но на записку. +Перечень источников закрыт и живёт в [каноне](../canon/references/canon.md), +раздел `adr/`. + **Триггер заведения, форма имени и правило замены — в [каноне](../canon/references/canon.md), раздел `adr/`.** Здесь они не повторяются: копия правила расходится с оригиналом на первой же смене версии @@ -106,9 +113,9 @@ description: Вести содержимое документов канона нет**. Строка «adr/ — не требуется: решение рутинное» и есть то, ради чего чек-лист существует; её отсутствие неотличимо от «забыл посмотреть». -Порядок работы: открой архивный `design.md` change, найди в `Decisions` то, что -проходит триггер, процитируй решение и его причину, сошлись на источник, добавь -строку в индекс `docs/adr/README.md` сверху. +Порядок работы: открой источник — архивный `design.md` change либо записку +разведки, — найди в нём решение, проходящее триггер, процитируй его и причину, +сошлись на источник, добавь строку в индекс `docs/adr/README.md` сверху. ## Чистка `architecture.md` diff --git a/av-dev-tasks/skills/tasks/references/task-research.md b/av-dev-tasks/skills/tasks/references/task-research.md index a097a82..9a419df 100644 --- a/av-dev-tasks/skills/tasks/references/task-research.md +++ b/av-dev-tasks/skills/tasks/references/task-research.md @@ -65,7 +65,10 @@ источники, что заведомо вне. 4. **Провести разведку** и **записать ответ по названному адресу**. Числа — с провенансом: с командой или условиями, которыми получены. Число без источника - проход ревью обязан читать как условие, а не как замер. + проход ревью обязан читать как условие, а не как замер. Проводит её конвейер + проекта — в плагине `av-dev-code` это скилл `resolve`, сценарий разведки; + плагина нет — разведка ведётся как проект привык, а этот скилл её только + заводит и закрывает. 5. **Разложить исход на задачи** — если он их родил. Разведка кончается одним из трёх: заведены задачи, записано знание, отказ. **Отказ — полноправный исход**: «проверили, не проблема» экономит работу.