Каталоги, агенты и общие дома переехали в av-dev/; скиллы названы по прежнему плагину — doc-*, task-*, code-*, с двумя смысловыми именами вместо тавтологии: doc-sync вместо docs, task-track вместо tasks. Манифесты сведены к двум плагинам. Пространства имён вызовов и пути внутри дерева переписаны машинно; проза, которая называет прежние плагины отдельными, идёт следующим шагом.
359 lines
33 KiB
Markdown
359 lines
33 KiB
Markdown
---
|
||
name: code-resolve
|
||
description: "Взять одну задачу и довести её до закрытия. Одна точка входа, три сценария, и выбирает сценарий сам скилл, прочитав постановку. Способ известен и меняется поведение — сценарий решения: цикл Spec Driven Development (opsx propose → разметка → ревью дизайна → чекпоинт с объяснением человеческим языком → opsx apply → ревью кода → archive → синк документации → коммит → закрытие). Способ известен, а спека не меняется (тип chore: тулчейн, зависимости, сборка, гит-хуки, перенос, чистка) — сценарий обслуживания: правка → гейт со сверкой состава проверок → ревью фиксированным планом без change (autotests, operations, плюс conventions, если тронут код) → синк документации → коммит → закрытие; планового стопа нет, change не заводится. Нашлась дельта-спека — задача оказалась шире своего типа: стоп с объяснением простым языком и двумя решениями человека, переформулировать запись в fix или feature и решать её процессом того типа следующим прогоном либо прекратить работу. Способа нет, постановка мутная, тип research — сценарий разведки: вопрос и рамки → чтение документов, кода и внешних источников (можно opsx:explore) → чекпоинт вариантов: 2–4 способа решить, цена каждого, что становится невозможным, рекомендация → ответ уезжает в документы канона, исход — в задачи → вычитка написанного → коммит → закрытие. Разведка кода не пишет и change не заводит, а выбранный способ реализуется следующим прогоном. На входе путь к файлу задачи, её слаг или просто текст. Использовать, когда просят взять, сделать или решить задачу, обновить зависимости или сборку, разобраться, изучить, сравнить подходы, проработать сырую идею, ответить на вопрос из беклога."
|
||
---
|
||
|
||
# Работа над одной задачей
|
||
|
||
Проводит **одну** задачу от постановки до закрытия. Вокруг планового стопа — без
|
||
согласований: механику не обсуждаем, делаем.
|
||
|
||
**Сценария три, а точка входа одна.** Какой из них идёт, решает **скилл**,
|
||
прочитав постановку, а не человек до вызова: «есть ли у задачи очевидный способ
|
||
решения» и «меняется ли то, что записано в спеке» видно после чтения записи, и
|
||
требовать этих суждений от вызывающего значит требовать их раньше, чем они
|
||
возможны.
|
||
|
||
| Сценарий | Когда | Чем кончается |
|
||
| --- | --- | --- |
|
||
| **решение** | способ известен, меняется поведение | код, ревью, архив, коммит, закрытие |
|
||
| **обслуживание** | способ известен, спека не меняется: тип `chore` | правка, ревью, синк, коммит, закрытие |
|
||
| **разведка** | способа нет: тип `research`, сырая идея, мутная постановка | ответ в документах, задачи, коммит, закрытие |
|
||
|
||
Ход каждого сценария живёт своим справочником: **решение** —
|
||
[references/solve.md](references/solve.md), **обслуживание** —
|
||
[references/maintain.md](references/maintain.md), **разведка** —
|
||
[references/research.md](references/research.md). Здесь только общее: вход,
|
||
развилка, правила, которые не зависят от сценария. Сценарии лежат порознь и
|
||
одинаково, потому что привилегированного среди них нет: тот, что жил бы прямо
|
||
здесь, читался бы как основной, а прочие — как оговорка.
|
||
|
||
## Предпосылки
|
||
|
||
- **OpenSpec и скиллы `opsx:*` — жёсткая предпосылка сценария решения**, а не
|
||
опция. На них стоят его шаги 2, 6 и 8, проход `review-specs` и ревью дизайна
|
||
(они завязаны на `openspec/changes/<id>/specs/*/spec.md` и на
|
||
`openspec validate --strict`). **Проект без OpenSpec этим скиллом не ведётся** —
|
||
подключай OpenSpec, а не вырождай цикл сценария; почему ветка деградации здесь
|
||
не
|
||
пишется, сказано в `av-dev:code-review`, раздел «Предпосылки», и дом у этого
|
||
довода там. Заводить руками не надо: каталог и настройку в `config.yaml`
|
||
делает скилл `av-dev:code-openspec`. **Сценариям разведки и обслуживания
|
||
OpenSpec не нужен** — они не заводят change; `opsx:explore` берётся разведкой,
|
||
если плагин есть.
|
||
- **Проектные копии этих скиллов и агентов удаляются при установке плагина**
|
||
(`.claude/skills/` — голые имена `resolve`, `review`, а у проектов прошлого
|
||
поколения ещё `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом
|
||
проекта: `<проект>-task-pipeline`, `<проект>-review-pipeline`;
|
||
`.claude/agents/<проект>-review-*.md`). Две копии одного скилла расходятся, и
|
||
побеждает та, что короче названа.
|
||
|
||
### Обращение к соседним плагинам
|
||
|
||
**Копия.** Дом — `shared/plugin-boundary.md` в репозитории плагинов: правило
|
||
общее для всех, кто зовёт чужое, и ни один плагин им не владеет. Правится дом, а
|
||
не этот файл.
|
||
|
||
<!-- копия: граница-плагинов из av-dev/shared/plugin-boundary.md -->
|
||
|
||
Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на
|
||
месте.
|
||
|
||
**Чужой скилл зовётся полным именем** — `av-dev:doc-canon`, `av-dev:task-track`,
|
||
`av-dev:code-review`. Короткое имя может разрешиться в устаревшую проектную копию
|
||
из `.claude/skills/`, и подмены не будет видно ни в докладе, ни в поведении.
|
||
|
||
**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт
|
||
только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо
|
||
откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он
|
||
прочитает его сам.
|
||
|
||
**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови
|
||
строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя,
|
||
пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже.
|
||
|
||
**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня
|
||
установленных плагинов проект не ведёт — он разошёлся бы с действительностью
|
||
молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.docs.json` —
|
||
канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер.
|
||
Имя файла — имя плагина, который его завёл, и держит он в том числе версию своего
|
||
формата: у канона документов и у каталога задач они свои и двигаются порознь.
|
||
|
||
<!-- /копия: граница-плагинов -->
|
||
|
||
Скилл зовёт `av-dev:code-review`, `av-dev:doc-sync` и
|
||
`av-dev:task-track`. Чем оборачивается отсутствие каждого — на самих шагах и в
|
||
разделе «Границы».
|
||
|
||
Перед стартом прочитай `CLAUDE.md` проекта и то, на что он ссылается, если ещё
|
||
не в контексте. Проектные факты, нужные ревью — инварианты, семантика гейта,
|
||
объёмы, модель угроз, прецеденты, — живут в **документах канона** `av-dev-docs`;
|
||
карта «что где» — `references/project-facts.md` конвейера ревью.
|
||
|
||
**Документов канона нет — проект к нему не приведён.** Скажи это строкой и
|
||
предложи скилл `av-dev:doc-canon`: одна операция на проект против поразрядной
|
||
деградации на каждой задаче. Работу при этом не останавливай.
|
||
|
||
## Вход
|
||
|
||
Задача задаётся **путём к файлу, именем файла, слагом или просто текстом**.
|
||
Ничего из этого не задано — попроси у вызывающего и остановись; сам в беклог не
|
||
лезь и приоритеты не интерпретируй: что делать дальше, решает не этот скилл.
|
||
|
||
**Запись из каталога сперва проверяется на готовность, и проверяет её машина.**
|
||
Вызови Skill `av-dev:task-track` и попроси прогнать `ready <слаг>`: он смотрит
|
||
тип, цель у `feature`, пустой ли раздел вопросов и собраны ли разделы схемы
|
||
типа. Судить это глазами нельзя — ровно тот случай, где машина дешевле и точнее,
|
||
а цена ошибки отложенная: недостающие критерии приёмки обнаружатся на приёмке,
|
||
когда сверять уже не с чем.
|
||
|
||
**`ready` отказал — это исход, а не препятствие для тебя.** Скажи, чего не
|
||
хватает, и остановись: дописывать чужую запись за автора не твоя работа. Исход —
|
||
«не доведена», с названной причиной.
|
||
|
||
**Отказ `ready` сценарий не выбирает.** Запись `research` без раздела «Вопрос»
|
||
(сырьё) — отказ и здесь: у неё нет вопроса, и разведывать нечего.
|
||
|
||
Плагина `av-dev-tasks` в проекте нет или задача пришла текстом — прогонять
|
||
нечего. Тогда прочитай постановку сам и скажи строкой, что готовность машиной не
|
||
проверялась; работу при этом не останавливай.
|
||
|
||
## Развилка: какой сценарий
|
||
|
||
Она в два вопроса, и оба стоят до всякой работы.
|
||
|
||
**Первый: есть ли у задачи один очевидный способ решения?**
|
||
|
||
- **нет** — тип `research`, сырая идея, новое и незнакомое, мутная постановка,
|
||
два подхода с разной ценой. **Сценарий разведки** —
|
||
[references/research.md](references/research.md);
|
||
- **есть** — что делать, понятно; спорно только как. Тогда второй вопрос.
|
||
|
||
**Второй: меняется ли то, что записано в `openspec/specs/`?**
|
||
|
||
- **меняется** — появляется или правится поведение. **Сценарий решения** —
|
||
[references/solve.md](references/solve.md);
|
||
- **не меняется** — тулчейн и сборка, зависимости, гит-хуки и шаги гейта,
|
||
перенос, чистка. **Сценарий обслуживания** —
|
||
[references/maintain.md](references/maintain.md).
|
||
|
||
**Второй вопрос решается связкой из двух признаков, и оба обязательны:** тип
|
||
записи предлагает (`chore`, реже `fix`, возвращающий поведение к уже
|
||
записанному), а отсутствие дельт подтверждает. Тип объявляет автор и может
|
||
ошибиться; отсутствие дельт — твоё суждение и принимается только вместе с типом.
|
||
Признаки разошлись — это стоп, а не выбор: скажи, что тип и предмет работы не
|
||
сходятся, и остановись. Подробно — [maintain.md](references/maintain.md), раздел
|
||
«Признак — связка, а не одно условие».
|
||
|
||
**Признак не в объёме работы, и это относится к обоим вопросам.** Крупная задача
|
||
с очевидным способом идёт в решение; маленькая, но незнакомая — в разведку;
|
||
однострочная правка, меняющая поведение, идёт полным циклом решения, а не
|
||
обслуживанием. Путь, выбираемый по самооценке размера, — самый дешёвый способ
|
||
«ускориться» и самый дорогой по последствиям. Тип `research` в разведку идёт
|
||
всегда: её исход знание, а не изменение системы.
|
||
|
||
**Назови выбранный сценарий вслух первой репликой** — одной строкой, с причиной.
|
||
Молча выбранный сценарий человек обнаруживает по тому, что работа пошла не туда,
|
||
и обнаруживает поздно.
|
||
|
||
### Сценарий выбирается один раз
|
||
|
||
**Смена сценария по ходу — событие, а не тихий поворот**, и каждая смена
|
||
устроена по-своему:
|
||
|
||
- **решение → разведка**: обнаружилось, что очевидного способа нет. Это **стоп**
|
||
с исходом «нужна разведка»: назови, что именно неясно, и не продолжай.
|
||
Кода к этому моменту не написано, и писать его «пока разбираемся» нельзя;
|
||
- **обслуживание → решение**: нашлась дельта-спека, то есть поведение всё-таки
|
||
меняется. Задача не сломалась — она **оказалась шире своего типа**, и стоп
|
||
здесь несёт человеку выбор: назови тип, которым она оказалась (`fix` —
|
||
расходится с заявленным, `feature` — снаружи появляется то, чего не было),
|
||
объясни простым языком, что нашлось, и дай два решения — **переформулировать
|
||
запись и решать процессом того типа следующим прогоном** либо **прекратить
|
||
работу**. Третьего — «доделать как обслуживание» — нет. Исход в обоих случаях
|
||
«меняется спека»; сделанное остаётся в рабочем дереве незакоммиченным, тип
|
||
меняет `av-dev:task-track` и только после ответа. Подробно —
|
||
[maintain.md](references/maintain.md), раздел «Дельта нашлась по ходу»;
|
||
- **обслуживание → разведка**: форма правки неизвестна (мажорное обновление,
|
||
смена сборщика). **Стоп** с исходом «нужна разведка», по тому же основанию,
|
||
что и у решения;
|
||
- **разведка → решение или обслуживание**: способ выбран на чекпоинте вариантов.
|
||
Разведка **всё равно доводится до конца** — ответ записан, задачи уточнены,
|
||
коммит сделан, — и работа идёт **следующим прогоном**, который запускает
|
||
человек.
|
||
|
||
Обратной смены «решение → обслуживание» нет: задача, заведшая change, доводится
|
||
циклом решения. Дельта-спеки, оказавшиеся пустыми, — находка ревью дизайна о
|
||
самой постановке, а не повод свернуть на короткий путь из середины длинного.
|
||
|
||
**Соблазн «разведаю по ходу» живёт именно здесь**, и он дорог тем, что выглядит
|
||
экономией одного прогона. Разведка внутри решения не имеет своего чекпоинта:
|
||
выбор делается тем, кто уже начал писать, и человек видит его только в
|
||
объяснении, где обсуждать выбор поздно. Ровно за это сценарии и разведены — не за
|
||
то, что это разные работы, а за то, что у них разные моменты для человека.
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
in["вход: файл, слаг или текст"]
|
||
ready["ready: готовность записи<br/>av-dev:task-track"]
|
||
fork{"есть очевидный<br/>способ решения?"}
|
||
fork2{"меняется ли<br/>спека?"}
|
||
solve["сценарий решения<br/>references/solve.md<br/>код, ревью, архив, коммит"]
|
||
main["сценарий обслуживания<br/>references/maintain.md<br/>правка, ревью, синк, коммит"]
|
||
res["сценарий разведки<br/>references/research.md<br/>ответ в документы и задачи"]
|
||
|
||
in --> ready --> fork
|
||
fork -->|"да"| fork2
|
||
fork -->|"нет"| res
|
||
fork2 -->|"да"| solve
|
||
fork2 -->|"нет: тип chore"| main
|
||
solve -.->|"способа всё же нет:<br/>стоп, кода не написано"| res
|
||
main -.->|"нашлась дельта: стоп,<br/>тип на fix или feature,<br/>следующим прогоном"| solve
|
||
main -.->|"форма неизвестна:<br/>стоп"| res
|
||
res -.->|"способ выбран:<br/>следующим прогоном,<br/>зовёт человек"| solve
|
||
```
|
||
|
||
Схема — **сводка**: содержание сценариев в их справочниках, и при расхождении
|
||
прав справочник.
|
||
|
||
## Автономность и плановый стоп
|
||
|
||
**У двух сценариев ровно один плановый стоп**, и стоят они в разных местах:
|
||
у решения — объяснение после ревью дизайна, у разведки — варианты до первого
|
||
написанного требования. Правило вокруг них общее.
|
||
|
||
**У обслуживания планового стопа нет вовсе, и это следствие, а не поблажка.**
|
||
Один стоп с ожиданием ответа у него всё же есть — по найденной дельта-спеке, — но
|
||
плановым он не является: через него проходят только те прогоны, где задача
|
||
оказалась не тем, чем объявлена.
|
||
Чекпоинт объясняет человеку **выбор**, а у обслуживания выбора нет по
|
||
построению: что делать, сказано в записи, и объяснение свелось бы к пересказу
|
||
задачи её же автору. Стоп, на котором нечего решать, вырождается в обряд
|
||
одобрения и обесценивает те стопы, где решать есть что. Правило необратимого
|
||
(ниже) действует там полностью и срабатывает чаще, чем в двух других сценариях:
|
||
выкладка, токены, хуки и чужие данные — обычное содержимое задач обслуживания.
|
||
|
||
**Вокруг чекпоинта умолчание прежнее — делать, а не спрашивать.** Чекпоинт не
|
||
отменяет автономность, он даёт развилкам плановое место, куда копиться.
|
||
|
||
Разрез простой:
|
||
|
||
- развилка найдена **до** чекпоинта — она его и ждёт. Не спрашивай отдельно:
|
||
чекпоинт рядом и стоит дёшево, а три вопроса подряд стоят дороже одного
|
||
разговора;
|
||
- развилка найдена **после** чекпоинта — старое правило: **запиши вопрос и доведи
|
||
остаток**, не останавливаясь.
|
||
|
||
Запись вопроса устроена так:
|
||
|
||
1. **Запиши там, где проект держит вопросы** (секция беклога, файл задачи,
|
||
трекер — это знает проект). Проект не сказал, куда, — отдельной секцией
|
||
`Вопросы` в своём докладе, и это тоже исход. Тело отвечает на три вещи: **что
|
||
именно решить**, **какие есть варианты и цена каждого**, **что стоит, пока
|
||
решения нет**. Плюс твоя рекомендация — человек чаще соглашается, чем выбирает
|
||
заново, и готовое суждение экономит ему весь контекст.
|
||
2. **Переформулируй задачу на остаток** — то, что делается без этого решения.
|
||
Назови границу: докуда доводим сейчас.
|
||
3. Доведи остаток до конца и закоммить. Задача не «висит на вопросе», она сделана
|
||
в объявленных границах. В разведке остаток — это ответ в объявленных рамках:
|
||
что успели узнать, где остановились и почему.
|
||
|
||
**Что остатком не является — правило живёт не здесь.** Канонический текст с обеими
|
||
оговорками — в плагине `av-dev-tasks`, скилл `av-dev:task-groom`, раздел
|
||
`## Вопрос, блокер, необратимое`, подраздел «Отличать вопрос от застревания».
|
||
Правило принадлежит управлению задачами, потому что решает **сделана задача или
|
||
вышла**, — это исход планирования, а не исполнения. **Ссылайся, не
|
||
пересказывай:** копия, заведённая здесь, уже однажды разошлась с оригиналом и
|
||
потеряла из перечня самое необратимое — запись **наружу**.
|
||
|
||
Коротко, чтобы знать, когда идти читать: остаток проверяется двумя порогами —
|
||
**материализация нерешённого** (запись состояния, зависящего от неотвеченного
|
||
вопроса) и **пол по пользе** (из остатка пропала польза, названная в постановке).
|
||
Оба порога — стоп: первый поднимает решение до начала записи, второй даёт исход
|
||
«не доведена».
|
||
|
||
Плагин `av-dev-tasks` не подключён — правило не отменяется, а становится
|
||
осторожнее: прежде чем записать зависящее от нерешённого куда бы то ни было —
|
||
в хранилище, в журнал, в витрину или наружу, — спрашивай человека.
|
||
|
||
Нет полезного остатка — задача заканчивается исходом «не доведена», вопрос
|
||
записан, ничего не коммитится наполовину.
|
||
|
||
### Когда спрашивать вне чекпоинта
|
||
|
||
По другому основанию — не «сложное решение», а **необратимое действие**:
|
||
|
||
- деплой, выкладка наружу, смена публичного адреса или токенов;
|
||
- удаление или перезапись рабочих данных, включая подрезку архивов;
|
||
- всё, что уходит за пределы машины.
|
||
|
||
Здесь ошибка не откатывается коммитом, поэтому спрашиваем даже когда решение
|
||
кажется очевидным.
|
||
|
||
## Границы: чем этот скилл не владеет
|
||
|
||
- **Беклогом, целями и приоритетами.** Задача приходит извне. Скилл её не
|
||
выбирает, не приоритизирует, не заводит и не переоценивает.
|
||
- **Форматом задач и документов.** Индексы и документы канона руками не правятся,
|
||
путь к чужому скрипту не выдумывается: этим владеют `av-dev:task-track` и
|
||
`av-dev:doc-sync`. Закрытие — работа этого скилла, и это осознанное решение с
|
||
названной ценой: **приёмщик и исполнитель совпали**. Закрытие поэтому **не окончательно** — человек на
|
||
груминге (`av-dev:task-groom`) возвращает задачу `reopen` с причиной, а доклад
|
||
по критериям приёмки становится единственным, по чему приёмка вообще возможна.
|
||
- **Определением ценности.** «Нужна ли эта функциональность» — не вопрос этого
|
||
скилла ни на одном шаге и ни в одном сценарии. Чекпоинт решения спрашивает «так
|
||
ли решаем», чекпоинт разведки — «каким из способов», но не «надо ли».
|
||
|
||
Что не принадлежит **отдельному сценарию**, названо у него же: урожай ревью и
|
||
выбор способа — в [solve.md](references/solve.md), изменение поведения и нарезка
|
||
пачки — в [maintain.md](references/maintain.md), код и приоритет — в
|
||
[research.md](references/research.md).
|
||
|
||
## Наблюдаемые исходы
|
||
|
||
**У каждого сценария их четыре**, и живут они у сценария:
|
||
[решение](references/solve.md) — сделана, не доведена, оказалась крупнее задачи,
|
||
нужна разведка; [обслуживание](references/maintain.md) — сделана, не доведена,
|
||
меняется спека, нужна разведка; [разведка](references/research.md) — способ
|
||
выбран, знание записано, отказ, не доведена.
|
||
|
||
Общего исхода нет намеренно. «Сделана» у решения и «знание записано» у разведки —
|
||
разные вещи с разной приёмкой, и слово, накрывающее оба, скрывало бы именно то,
|
||
чем прогон кончился. «Сделана» у решения и у обслуживания совпадает словом, но не
|
||
определением: у первого в него входит пройденный чекпоинт и заархивированный
|
||
change, у второго — сверенный состав гейта и синк.
|
||
|
||
## Доклад
|
||
|
||
Ядро общее, и в нём обязательно:
|
||
|
||
- **какой сценарий шёл** — решение, обслуживание или разведка, — и почему выбран
|
||
он;
|
||
- **исход** одним из четырёх слов своего сценария и, если он не благополучный,
|
||
чем ограничен результат;
|
||
- что сделано, какие вопросы записаны и куда;
|
||
- чего проверить или узнать **не удалось**.
|
||
|
||
Сверх ядра каждый сценарий добавляет своё: [solve.md](references/solve.md) —
|
||
чекпоинт, change, критерии приёмки, урожай и границы покрытия;
|
||
[maintain.md](references/maintain.md) — чем подтверждён признак, состав гейта до
|
||
и после, критерии приёмки, урожай и границы покрытия;
|
||
[research.md](references/research.md) — вопрос и ответ, адреса записи, заведённые
|
||
задачи, рамки.
|
||
|
||
## Тонкости
|
||
|
||
- **Не завязывайся на основную ветку и корень репозитория.** Скилл работает в
|
||
текущем worktree и на текущей ветке: не делай `git checkout`/`switch`, не
|
||
создавай веток, не пушь.
|
||
- Прогон проходит **не больше одного** чекпоинта, и это норма, а не упрощение.
|
||
Два стопа за одну задачу — цена незнания способа, и платится она двумя
|
||
прогонами, а не одним длинным. У обслуживания чекпоинта нет ни одного, и это
|
||
тоже норма: там нечего решать.
|
||
- Держи вызывающего в цикле короткими репликами на переходах фаз, но не проси
|
||
подтверждать механику: чекпоинт — единственное место, где ждут ответа, а в
|
||
обслуживании такого места нет вовсе.
|
||
- **Сценарий назван вслух — значит, его можно оспорить.** Человек, увидевший в
|
||
первой реплике «иду разведкой, потому что способа не видно», поправит выбор
|
||
одной фразой; молча выбранный сценарий он поправит через полчаса работы.
|