Третий заход по находкам ревью — то, что старше темы 78 и тянулось с тем 74–77. Оснований у развилки три во всех местах: конвейер называл два, а устав триажа, контракт находок, сценарий решения и журнал — три. Там же сказано, чем третье отличается: по первым двум оркестратор урезает изменение до остатка, третье отменяет одобрение и возвращает на чекпоинт. Вопросы проекта по темам достались проходам, которые эти темы закрывают: review-code, review-specs и review-autotests получили обязанность отвечать дословно и строку в блоке покрытия. Прежде конвейер обещал их каждому проходу, а знал о них только приёмник тем. Глубокое ревью приведено к уставам, которые зовёт: глубина у проходов разная — доказательство у тех двоих, что держат машину, разбор у architecture и code; у триажа три вызывающих, а не два режима, и потолка в 7 пунктов там нет. Версия раскладки поднята до 5 с записью журнала: скелет docs/review.md потерял подраздел «Триггеры метки» ещё темой 77, а миграции проектам никто не дал. Сняты остатки меток в task-track и в config-skeleton, уезжающем в чужой проект. Перечень осей досчитал три оси: глубина темы, разметка действия, род правки. Журнал — тема 81.
745 lines
69 KiB
Markdown
745 lines
69 KiB
Markdown
---
|
||
name: task-track
|
||
description: Ведение задач как каталога markdown-файлов (одна задача = один файл в items/ + строка в BACKLOG.md). У каждой задачи есть тип (feature, fix, chore, research), и тип решает, каких разделов она требует и что с ней можно делать. У проекта есть стадия (build — беклог это план стройки, порядок строк значит зависимость; support — очередь правок, порядок значит важность). Заведение записи из диалога, разбор находок аудита/ревью, декомпозиция на независимо полезные части, штурм сырья, гигиена полей, смена стадии и проверка согласованности индекса. Использовать, когда просят добавить задачу или идею, превратить находки ревью в задачи, разбить задачу, проработать идею, поправить формат, объявить стадию или проверить беклог. Каталог отстал от версии раскладки — это скажет tasks.py check, а повышает проект скилл av-dev:canon по общему журналу версий. Расстановка приоритетов и разбор накопившегося — скилл av-dev:task-groom. Не реализует задачи — этим занимается скилл решения задачи.
|
||
---
|
||
|
||
# Задачи
|
||
|
||
Задачи — каталог markdown-файлов. Одна задача = один файл `items/<slug>.md` плюс
|
||
строка в `BACKLOG.md`. Скилл владеет **форматом и содержимым**: заводит,
|
||
редактирует, закрывает, разбирает находки ревью, дробит, штурмует сырьё.
|
||
|
||
Чем он **не** владеет: **очередью** — что делать следующим и что перестало быть
|
||
важным, решает скилл `task-groom`, а этот скилл лишь даёт ему операции; и выполнением
|
||
задачи — это конвейер проекта.
|
||
|
||
## Шесть правил, из которых всё следует
|
||
|
||
Ситуация не покрыта инструкцией — решай по ним.
|
||
|
||
0. **Стадия решает, что значит порядок строк.** Проект живёт в одной из двух
|
||
стадий, и обе ведут один и тот же беклог, но читают его по-разному.
|
||
На **стройке** (`build`) беклог это план от базы к деталям: порядок —
|
||
зависимость, «раньше нельзя». На **доработке** (`support`) беклог это очередь
|
||
правок: порядок — важность, «раньше лучше». Из этого следует остальное —
|
||
сколько у беклога секций, как его пополняют, что значит его опустошение и
|
||
нужен ли груминг. Стадия объявлена ключом `[tasks] stage`; молчание ответом
|
||
не считается, и `check` без неё отказывает.
|
||
1. **Беклог гниёт с той стороны, где его пополняют — на доработке.** Заведение
|
||
там самая частая операция и с худшим отказом: из одного разговора рождается
|
||
пять файлов, а переоценка потом разгребает то, чего не надо было заводить.
|
||
Дедупликация и фильтр на входе дешевле любой чистки: заводим только то, что
|
||
**не делаем сейчас** и о потере чего пожалеем.
|
||
|
||
**На стройке правило не применяется**, и это не послабление. Список стройки
|
||
пишется вперёд целиком — он и есть замысел, — а фильтр «не заводи то, чего не
|
||
делаешь сейчас» запретил бы написать план дальше первого шага. Дедуп остаётся
|
||
в обеих стадиях: две записи об одном плохи всегда.
|
||
2. **Файл — источник истины, индекс производен.** Разошлись — неправ индекс.
|
||
Согласованность механизируема и проверяется командой, а не вниманием: всё,
|
||
что ловит `tasks.py check`, не должно попадать ни в чек-лист, ни в промпт.
|
||
Поэтому **«зачем» живёт в мете файла**, а строка индекса его лишь
|
||
повторяет: пока поле лежало только в индексе, восстановление пропавшей
|
||
строки теряло его молча и навсегда. Единственное исключение намеренное:
|
||
**порядок строк в беклоге** — он свойство списка, а не задачи, и в файле ему
|
||
места нет (правило 4).
|
||
3. **Причина переживает запись.** Выкинутая без причины задача вернётся через
|
||
квартал тем же текстом. Реализованная оставляет след в коммите — выкинутая не
|
||
оставляет ничего, поэтому у неё есть `REJECTED.md`.
|
||
4. **Порядок строк — единственное, чего в файле нет.** Он значим в обеих
|
||
стадиях, и назначает его человек: на стройке — раскладывая шаги по
|
||
зависимости, на доработке — на груминге. Машина порядок не выводит и не
|
||
угадывает; всё, что она делает сама, — ставит машинную позицию в **конец**
|
||
секции и говорит об этом вслух.
|
||
|
||
**Дом порядка — индекс, а не файл.** Положи его в файл числом, и два соседних
|
||
файла смогли бы утверждать одно и то же место, а строка индекса —
|
||
противоречить обоим.
|
||
|
||
Одно место в очереди назначено **не человеком, а типом**: **сырьё**
|
||
(`research` без раздела «Вопрос») стоит в конце своей секции. Его не берут,
|
||
и между берущимся оно каждый раз требует открыть файл, чтобы это понять. Раз
|
||
это выводится, проверяет и чинит это машина.
|
||
5. **Тип решает, что с задачей можно делать.** Тип — вторая ось и первое
|
||
поле меты: от него зависит, какие разделы обязательны в теле и берётся ли
|
||
запись в работу. Словарь закрыт; ни один тип не подошёл — значит, в записи их
|
||
два, и её надо разделить.
|
||
|
||
## Раскладка
|
||
|
||
Каталог задач — **`tasks/` в корне репозитория, жёстко.** Он принадлежит этому
|
||
скиллу, а не канону документов: учёт работ ведут и в проекте, который к канону
|
||
не приведён, и каталога `docs/` там нет вовсе. Внутри
|
||
`docs/` задачи лежали до версии канона 11; непереехавший проект скрипт
|
||
по-прежнему находит, но новый заводит только в корне.
|
||
|
||
```
|
||
tasks/
|
||
items/ задачи файлами, <slug>.md, слаги английские
|
||
BACKLOG.md что можно взять. Порядок строк в секции значим,
|
||
и значит он разное на разных стадиях
|
||
REJECTED.md ушедшее БЕЗ реализации, с причиной и датой
|
||
```
|
||
|
||
**Индекс один.** `REJECTED.md` индексом не считается: он не говорит, где запись
|
||
числится, — это кладбище ушедшего.
|
||
|
||
**Секции беклога называет проект**, и `check` проверяет у них ровно две вещи:
|
||
что секция есть хоть одна и что на стройке она **одна**. Смысла секции не несут
|
||
— это полки домена (`Ядро`, `Инфра`), — и подгонять их имена под свой вкус
|
||
скрипт права не имеет. Поле меты, называющее полку, зовётся **Категория**.
|
||
|
||
**Заголовок секции отбит пустой строкой с обеих сторон и написан с прописной**;
|
||
отбивку правит `check --fix`. Написание секции в мете файлов он тоже правит: имя
|
||
секции принадлежит заголовку индекса, файл на неё только ссылается.
|
||
|
||
**Секции «блокеры» в беклоге нет.** Блокер — это *состояние* (работа не может
|
||
продолжаться ни одной задачей), а не полка: он живёт ровно до ответа человека, и
|
||
записи в такой секции не успевают жить. Следы блокера остаются вопросами в
|
||
файлах задач. Постоянно пустая секция со старой семантикой
|
||
«разбираются пачками» противоречила бы правилу «блокер эскалируется немедленно»,
|
||
поэтому `init` её заводить отказывается, а `check` о ней говорит. **Проекту,
|
||
который переезжает с такой секцией, её надо удалить** — это единственное место,
|
||
где это сказано.
|
||
|
||
**Порядок строк — единственное, чего в файле нет** (правило 4). Отсюда следствие
|
||
для всякой машинной правки индекса: восстановленная или перенесённая строка
|
||
встаёт **в конец своей секции**, и скрипт об этом говорит. Молчаливая вставка
|
||
выдала бы машинную позицию за решение человека — а решение это его.
|
||
|
||
**У сделанной задачи записи не остаётся** — файл и строка удаляются (`close
|
||
--implemented`). Ей хватает коммита и документации проекта; вторая запись была
|
||
бы вторым домом для того же факта. Вопрос «что было сделано и когда» отвечается
|
||
даром: индекс лежит под git, а закрытие коммитится отдельным коммитом учёта —
|
||
`git log -p tasks/BACKLOG.md` отдаёт историю без отдельного журнала.
|
||
|
||
Куда запись может переехать и какой командой — весь набор переходов:
|
||
|
||
```mermaid
|
||
stateDiagram-v2
|
||
state "BACKLOG.md — что берут" as B
|
||
state "REJECTED.md — ушла без реализации" as R
|
||
state "записи нет — реализована" as D
|
||
|
||
[*] --> B: add --type feature|fix|chore|research
|
||
B --> B: move --after | --first | --section
|
||
B --> D: close --implemented
|
||
B --> R: close --reason
|
||
D --> B: reopen --reason
|
||
R --> B: reopen --reason
|
||
```
|
||
|
||
Состояния здесь — **где числится строка**, а не где лежит файл: файл
|
||
`items/<slug>.md` не двигается ни на одном переходе. Стрелок «руками» на схеме
|
||
нет намеренно — каждый переход это команда, и другого способа его совершить не
|
||
существует.
|
||
|
||
Схема — **сводка**: условия и оговорки живут в тексте разделов, и при
|
||
расхождении прав текст.
|
||
|
||
## Две стадии
|
||
|
||
**Стадия проекта — ось, и решает она, что значит порядок строк беклога.**
|
||
Значения два, дом — ключ `[tasks] stage` в `.av-dev.toml`.
|
||
|
||
| | `build` — стройка | `support` — доработка |
|
||
| --- | --- | --- |
|
||
| Порядок строк | зависимость: раньше **нельзя** | важность: раньше **лучше** |
|
||
| Секции | ровно одна: список от базы к деталям | полки домена, сколько нужно |
|
||
| Заведение | список пишется вперёд целиком | по одной, по мере появления |
|
||
| Пустой беклог | план исчерпан, стройка окончена | нормальное состояние |
|
||
| Груминг | не применяется; замысел сменился — план пересматривается целиком | основная гигиена, порциями по 5–8 |
|
||
| Залежалость | не считается: шаг ждёт своей очереди законно | считается, `list --stale` |
|
||
|
||
**Стадия называется явно, и молчание ответом не считается.** Без неё порядок
|
||
строк нечем прочитать: переставить строку значит на стройке сломать план, а на
|
||
доработке — принять решение о важности, и это разные действия. `init --stage`
|
||
обязателен, `check` без ключа отказывает, `check --fix` его не подставляет:
|
||
какая стадия у проекта, знает человек, а подставленное умолчание соврало бы ровно
|
||
там, где по нему принимают решение.
|
||
|
||
**Секций на стройке одна, и это не педантизм.** Порядок там — зависимость, и
|
||
разложенный по полкам список перестаёт быть планом: два шага из разных секций
|
||
уже не сравнить. На доработке полки законны — правки независимы, и очередь
|
||
внутри полки самостоятельна.
|
||
|
||
**Переход — событие, а не настройка.** `tasks.py stage support` переносит остаток
|
||
беклога в первую новую секцию, правит «Категорию» в файлах и говорит, что порядок
|
||
с этого момента значит другое. Датой ему служит коммит: отдельного журнала ради
|
||
одной строки не заводится. Признак созревания наблюдаемый — беклог стройки
|
||
исчерпан, и `check` об этом напоминает; **запретить переход раньше скрипт не
|
||
берётся**: «приложение построено» решает человек, а не счётчик строк.
|
||
|
||
Обратный переход (`stage build`) разрешён и устроен так же. Он редок — проект
|
||
уходит на стройку заново разве что при переделке замысла целиком, — но
|
||
запрещать его было бы запретом на то, что иногда и правда случается.
|
||
|
||
## Чего у задач больше нет
|
||
|
||
**Тип `goal` и `ROADMAP.md` упразднены.** Цель была зонтиком над параллельными
|
||
направлениями: она нужна там, где список работ нельзя выстроить в один порядок,
|
||
и очередь идёт поперёк направлений. У проекта, который ведёт один человек, такого
|
||
не бывает — на стройке список линеен по зависимости, на доработке правки
|
||
независимы, — и зонтик не стоял ни над чем.
|
||
|
||
Роадмап при этом отвечал на свой вопрос наполовину: «чего ещё не умеет» — это
|
||
«что осталось в беклоге», то есть пересказ второго индекса. Вторая половина, «что
|
||
уже умеет», живёт в двух домах и без него: нормативное поведение — в
|
||
`openspec/specs/`, а когда и в каком порядке оно появилось — в `git log` индекса
|
||
и коммитах задач.
|
||
|
||
Вместе с целью ушли: секция `Готово` (её ответ дают спеки и история), теги
|
||
`goal:<слаг>` и `decomposed`, поле меты `Секция` (осталась `Категория`), раздел
|
||
`Завершение`, ключи `[tasks] roadmap` и `[tasks] completion_heading`, флаги
|
||
`add --goal`, `list --goal`, `list --index`, `edit --goal`, `edit --section` и
|
||
`init --roadmap`. Встретились в проекте —
|
||
`check` назовёт их поимённо, `check --fix` снимет теги, а запись типа `goal`
|
||
оставит человеку: во что она превращается — в задачу или в ничто, — машина не
|
||
решает.
|
||
|
||
**Тип `[epic]` упразднён раньше и не вернулся.** Слишком крупный шаг дробится на
|
||
шаги помельче, стоящие в списке подряд.
|
||
|
||
## Тип записи
|
||
|
||
**Тип решает, что с задачей можно делать.** Вторая ось скилла — первая стадия.
|
||
Перечень осей всего процесса и того, чего каждая **не** решает, —
|
||
[shared/axes.md](../../shared/axes.md). Дом типа —
|
||
**поле меты `Тип` первой строкой**; эмодзи в заголовке H1 от него производна, её
|
||
ставит `add` и чинит `check --fix`.
|
||
|
||
| Тип | Обязательные разделы | Устав |
|
||
| --- | --- | --- |
|
||
| ✨ `feature` | `Затрагивает`, `Критерии приёмки` | [task-feature.md](references/task-feature.md) |
|
||
| 🐞 `fix` | `Воспроизведение`, `Затрагивает`, `Критерии приёмки` | [task-fix.md](references/task-fix.md) |
|
||
| 🧹 `chore` | `Затрагивает`, `Критерии приёмки` | [task-chore.md](references/task-chore.md) |
|
||
| 🔬 `research` | `Вопрос`, `Куда ляжет ответ` | [task-research.md](references/task-research.md) |
|
||
|
||
Берутся в работу все четыре: записи, которую нельзя взять, больше не существует.
|
||
|
||
Сверх обязательных у любой задачи допустимы `Рамки` и `Вопросы`. Раздел не из
|
||
схемы своего типа — **замечание, а не ошибка**: свой раздел законная вольность
|
||
проекта, но `Воспроизведение` у `chore` почти всегда значит, что тип проставлен
|
||
не тот, и сказать об этом стоит, не запрещая.
|
||
|
||
**Прежних осей было две, и ортогональность у них была фальшивой.** Тип записи
|
||
(`goal`/`idea`/`task`) и род работы (`kind:<род>` тегом) давали двенадцать клеток
|
||
произведения, из которых законны были шесть: у цели род запрещён, у задачи
|
||
обязателен, у идеи пуст. Плюс алгоритм работы крепится не к `task`, а к `fix` и
|
||
`research` — то есть к роду. Оси схлопнуты, тег `kind:` упразднён.
|
||
|
||
**Тип `idea` упразднён вместе с ними.** Он значил не род работы, а **состояние
|
||
незаполненности** — «первый, второй или третий вопрос теста готовности не
|
||
отвечается», — а состояние типом быть не может: оно меняется по мере того, как
|
||
запись дописывают, а тип меняют командой. Теперь это состояние называется честно:
|
||
`research` без раздела «Вопрос» — **сырьё**. В работу не берётся ровно как
|
||
прежняя идея, лежит в конце своей категории и отбирается `list --raw`.
|
||
|
||
Словарь **закрыт**. Открытый разъедется на синонимах — `bug`, `bugfix`, `fix`,
|
||
`defect`, — и отбор по типу перестанет отвечать на свой единственный вопрос. Ни
|
||
один тип не подходит — это сигнал, что в задаче их два и её надо разделить.
|
||
|
||
**Требуется тип там, где по нему принимают решение:** `ready` без типа
|
||
откажет, потому что не знает, каких разделов требовать. `check` о пропаже только
|
||
**напоминает** — беклог, заведённый до появления типа, законен, и переоформлять
|
||
его «заодно» здесь не просят.
|
||
|
||
**Тип не выбирает состав ревью и глубину проверки — и не выбирает их больше
|
||
никто.** Состав прогона постоянный: он один и тот же на всякой задаче
|
||
(`av-dev:code-review`, «Состав прогона»). Прежде состав считала метка `small` ·
|
||
`medium` · `large`, и тогда эта строка отвечала на живой вопрос «не задаёт ли её
|
||
тип»; метки нет, и вопрос снят вместе с ней. Правило «предписание процесса в теле
|
||
задачи снимается» типом не отменяется, а подтверждается: он описывает работу, а
|
||
не то, как её проверять. **Стадия проекта состава тоже не выбирает**: изменение
|
||
на стройке ничем не проще того же изменения на доработке.
|
||
|
||
**Одно исполнителю тип всё же говорит — каким сценарием работу вести, и то не
|
||
один.** Скилл `av-dev:code-resolve` выбирает сценарий связкой из двух
|
||
признаков: тип **предлагает** (`chore` — обслуживание, `research` — разведка),
|
||
а подтверждает его предмет работы — есть ли что менять в спеках. Признаки
|
||
разошлись — работа останавливается, и тип меняется здесь, командой `edit --type`,
|
||
а не переклеивается исполнителем по ходу. Состава ревью это по-прежнему не
|
||
задаёт: он постоянный, а на прогоне без change его называет сам сценарий.
|
||
|
||
## Как написана задача
|
||
|
||
Три требования к тексту. Первое — про заголовок, два остальных про то, чтобы
|
||
задачу можно было **оценить, не открывая код**.
|
||
|
||
**Заголовок отвечает на вопрос своего типа.** Вопросов два, поэтому и форм две:
|
||
|
||
| Тип | Отвечает на | Пример |
|
||
| --- | --- | --- |
|
||
| ✨ `feature`, 🐞 `fix`, 🧹 `chore` | что нужно сделать | Печатать поле одним куском кода |
|
||
| 🔬 `research` | о чём разведка | Подсказка следующего хода |
|
||
|
||
Задача — **глаголом в неопределённой форме**, перед ним допускается «не»: «Не
|
||
отбрасывать молча лишние символы в ходе», а не «Лишние символы молча
|
||
отбрасываются». Описательный заголовок называет **состояние**, а из состояния не
|
||
видно, чего от работы ждут: «Ничья объявляется, пока клетки есть» одинаково
|
||
читается и как жалоба, и как задание, — и в списке, где решают «брать или не
|
||
брать», это разные вещи. `research` формы действия не несёт **намеренно**: её
|
||
исход знание, а что делать — ещё неизвестно, и заголовок-действие обещал бы
|
||
решённость, которой нет.
|
||
|
||
`check` считает заголовки не в форме действия и печатает **число** в блоке
|
||
здоровья, не замечанием на файл: проверка эвристическая (первое слово на
|
||
`-ть`/`-ти`/`-чь`), а беклог, заведённый до правила, не переоформляют «заодно».
|
||
Годность формулировки — не машине: её смотрит
|
||
[агент вычитки](#вычитка-два-прохода-а-не-один).
|
||
|
||
**Функции и границы, а не намерения.** Задача называет, что система начнёт
|
||
делать, и какие границы это трогает: эндпоинт или команду, таблицу и миграцию,
|
||
формат на диске, публичный тип пакета, внешний сервис. Перечень живёт разделом
|
||
«Затрагивает» (форма — [references/task-format.md](references/task-format.md)) и
|
||
требуется к взятию в работу. Без него задача оценивается по объёму текста, а не
|
||
по объёму поверхности, — и оценка систематически занижена ровно там, где текст
|
||
короткий, а границ много. Названы **границы**, а не то, как они изменятся: план
|
||
реализации живёт в предложении об изменении, а не в задаче.
|
||
|
||
**Предметно, но без усложнения.** Текст задачи читает человек, который решает,
|
||
брать её или нет, и делает это по строке индекса и одному экрану тела.
|
||
|
||
Язык — общий для всех проектных текстов, и дом у него один:
|
||
[shared/language.md](../../shared/language.md) — информационный стиль,
|
||
применённый к задачам и документам канона; там же таблицы англицизмов и жаргона
|
||
и то, что из стиля отброшено намеренно. Задаче он даёт четыре требования,
|
||
которые нарушаются чаще прочих:
|
||
|
||
- **глагол вместо отглагольного существительного**: «обработчик не проверяет
|
||
владельца», а не «проверка владельца не осуществляется»;
|
||
- **факт вместо оценки**: «время ответа доходит до 800 мс», а не «работает
|
||
медленно». Оценка без факта рядом — настроение, а не сведение;
|
||
- **англицизм с живым русским аналогом заменяется**: не «зафиксить флоу», а
|
||
«починить порядок доставки». Имя вещи не переводится: слаг, команда, тип в
|
||
коде, `API`;
|
||
- **термин не из документов проекта вводится одной строкой** или не
|
||
употребляется. Свой словарь у задачи — самый дешёвый способ сделать беклог
|
||
нечитаемым для того, кто вернётся к нему через квартал.
|
||
|
||
И одно требование, которое есть только у задачи: **сложность формулировки — не
|
||
признак сложности работы.** Задачу, которую не удаётся сказать просто, чаще
|
||
всего не удаётся и оценить: это либо две задачи, либо сырьё.
|
||
|
||
Эти правила — про **язык**, а не про объём: короткая задача без границ хуже
|
||
длинной с ними.
|
||
|
||
## Инструмент (`tasks.py`)
|
||
|
||
Пусть `tk="$CLAUDE_PLUGIN_ROOT/skills/task-track/scripts/tasks.py"`, а `D` —
|
||
`tasks` от корня проекта. `--dir` стоит в примерах намеренно: вызов из
|
||
подкаталога — обычное дело.
|
||
|
||
```
|
||
python3 $tk check --dir D # согласованность индекса + здоровье
|
||
python3 $tk check --dir D --fix # + починить дрейф (тип, эмодзи, место, заголовок, дубли, «зачем», форма меты)
|
||
python3 $tk list --dir D [--stale] [--section S] [--type T] [--tag a,b] [--raw] [--questions]
|
||
python3 $tk add --dir D --slug S --title T --type feature|fix|chore|research [--section S] [--why «зачем»] [--tag a,b]
|
||
python3 $tk edit S --dir D [--title T] [--why «зачем»] [--type T] [--add-tag a,b] [--rm-tag c]
|
||
python3 $tk move S --dir D [--section S] [--reason R] [--after S | --first] # без --section — текущая секция
|
||
python3 $tk close S --dir D --reason R # в REJECTED.md + удалить (ушла без реализации)
|
||
python3 $tk close S --dir D --implemented # просто удалить (реализована и закоммичена)
|
||
python3 $tk reopen S --dir D --reason R # вернуть закрытую: приёмка не сошлась
|
||
python3 $tk ready S… --dir D # схема типа выполнена — можно брать в работу
|
||
python3 $tk stage --dir D # показать стадию
|
||
python3 $tk stage support --dir D [--sections …] # сменить стадию: секции и смысл порядка
|
||
python3 $tk init --dir D --stage build|support [--sections …] [--items …] …
|
||
python3 $tk adopt scan --from … --stage S | apply --plan … # разовая адаптация, references/adopt.md
|
||
```
|
||
|
||
**Копия.** Дом словаря — `shared/axes.md` в репозитории плагина: словарь общий
|
||
для всех скриптов, и ни один скилл им не владеет. Правится дом, а не этот файл.
|
||
|
||
<!-- копия: коды-выхода из av-dev/shared/axes.md -->
|
||
|
||
**Коды выхода — общий словарь всех скриптов `av-dev`. Ветвись на коде, а не на
|
||
тексте вывода.**
|
||
|
||
| Код | Что случилось |
|
||
| --- | --- |
|
||
| 0 | сошлось |
|
||
| 1 | дрейф: рабочая ситуация, чинится |
|
||
| 2 | ошибка употребления: аргументы или нарушенное правило |
|
||
| 3 | окружение: не тот каталог, битый конфиг, нет инструмента |
|
||
| 4 | внутренний сбой — дефект скрипта, доложить |
|
||
|
||
**Различать 1 и 3 обязательно.** «Дрейф» — рабочая ситуация, и чинится она
|
||
правкой предмета; «окружение» — нерабочая, и повтор той же командой не поможет.
|
||
Одинаковая реакция на них неверна в обоих случаях.
|
||
|
||
<!-- /копия: коды-выхода -->
|
||
|
||
Здесь это значит: код 1 приходит **только от `check`** — найден дрейф индекса и
|
||
файлов, чинится `check --fix`, остаток разбирается руками. Код 3 — каталог не
|
||
найден, конфиг битый или мимо диска: чинится путём или `.av-dev.toml` в корне.
|
||
|
||
Тип — английское ключевое слово `feature` / `fix` / `chore` / `research` (как и
|
||
прочие токены команд), у `add` **обязательное**: без него неизвестно, какой
|
||
шаблон тела класть. Стадия — такое же слово, `build` / `support`, и у `init` она
|
||
обязательна по той же причине: без неё неизвестно, что писать в шапке беклога и
|
||
сколько заводить секций. Текст задачи при этом русский, а эмодзи в заголовке
|
||
ставит скрипт.
|
||
|
||
**Мутации правят файл и индекс заодно** — руками строку индекса или мету
|
||
не пиши, зови `add`/`edit`/`move`/`close`/`reopen`. Смена заголовка, «зачем», типа
|
||
и **тегов** — это `edit`: он держит H1 (вместе с эмодзи), мету и индекс
|
||
согласованными. Снятие тега — `--rm-tag` (после ответа на вопрос снимается
|
||
`question`), смена типа — `--type`; оба заменяют прежнее значение, а не
|
||
добавляют второе.
|
||
|
||
**Секцию меняет только `move`, и он пишет причину**: смена полки без причины и
|
||
есть тот дрейф, который потом никто не объяснит.
|
||
|
||
**`move --after <слаг>` и `move --first` — это и есть расстановка порядка.**
|
||
Порядок строк в секции значим (правило 4), и двигают его только этой командой:
|
||
руками поправленная строка не оставляет причины, а причина здесь и есть половина
|
||
решения. Что именно этот порядок значит, говорит стадия: на стройке `--after`
|
||
называет зависимость, на доработке — приоритет.
|
||
|
||
Тело задачи скрипт не трогает:
|
||
`add` кладёт заголовок, мета-блок и шаблон с подсказками, тело дописываешь
|
||
редактором (пока плейсхолдер на месте, `check` напоминает).
|
||
|
||
`check` — единственный судья согласованности; что именно он ловит, скажет его
|
||
вывод, здесь не пересказываем. Гоняй его **в начале сессии** и **после каждой
|
||
правки**, даже если правил мутациями: дрейф мог накопиться раньше. Накопившееся
|
||
чини `check --fix` — он детерминированно правит то, где истина однозначна (тип в
|
||
своё поле, эмодзи заголовка, имя поля места, секция, заголовок, дубли, «зачем» из
|
||
индекса в файл, старая форма меты, снятые теги упразднённых целей, сырьё
|
||
в конец секции), а неоднозначное (нечего восстанавливать, **тип, которого
|
||
неоткуда взять**, запись типа `goal`) печатает отдельной пометкой
|
||
`НЕОДНОЗНАЧНО` — это тебе, и это идёт строкой доклада. **Ссылка на исчезнувший
|
||
файл в пометку не попадает:** `--fix` её просто не трогает, и она остаётся
|
||
`ОШИБКА` обычного `check` — то есть видна, но в докладе её надо назвать отдельно.
|
||
|
||
`--fix` правит **и файлы** — там, где источник ровно один и выбирать не из чего:
|
||
тип переезжает из прежнего дома (тег `kind:`, префикс `[goal]`/`[idea]`) в поле
|
||
меты, заголовок получает эмодзи, поле места зовётся «Категория», «зачем»,
|
||
оставшееся только в индексе, переезжает в мету, теги `goal:` и `decomposed`
|
||
снимаются. Каждый случай печатается поимённо.
|
||
|
||
**Ни стадию, ни состав секций `--fix` не трогает.** Стадию он подставить не
|
||
может — это решение человека; секции стройки не сливает — в каком порядке пойдут
|
||
строки слитых полок, знает тоже только человек, а порядок здесь и есть
|
||
содержание.
|
||
|
||
**Тип, который не выводится ниоткуда, `--fix` не угадывает.** `feature` от
|
||
`chore` машина не отличает, и подставленное наугад значение врало бы ровно там,
|
||
где по нему принимают решение. Такие записи идут в `НЕОДНОЗНАЧНО`, и тип им
|
||
проставляет человек — `edit <слаг> --type …`.
|
||
|
||
**Что механизировано, а что нет.** Схему типа проверяет `ready` на входе в
|
||
работу — там, где по ней принимают решение; `check` поимённо о ней не говорит, а
|
||
считает: строка здоровья **«схема типа не выполнена: N из M»** называет число и
|
||
первые слаги, строка **«готово к взятию»** — сколько задач беклога пройдут
|
||
`ready` целиком (схема плюс отсутствие открытого вопроса). Это две
|
||
разные строки, и совпадение их чисел — совпадение. У каждой части своя глубина:
|
||
|
||
- **тип** — жёстко: назван и из закрытого словаря;
|
||
- **критерии приёмки** (`feature`, `fix`, `chore`) — число пунктов жёстко
|
||
(меньше двух отказ, больше пяти замечание), наличие оракула **эвристикой** по
|
||
слову «оракул» в пункте;
|
||
- **прочие разделы схемы** (`Затрагивает`, `Воспроизведение`, `Вопрос`,
|
||
`Куда ляжет ответ`) — только **наличие непустого**. Содержимое
|
||
машине не видно: границу, которую забыли назвать, она от отсутствующей не
|
||
отличает, а шаги, по которым ничего не воспроизводится, — от годных.
|
||
|
||
Настоящий оракул от слова «оракул» машина тоже не отличает, поэтому эвристика
|
||
даёт только замечание, и в докладе это называется как есть: «проверено наличие
|
||
разделов своего типа и число критериев, годность оракулов и полнота границ —
|
||
глазами».
|
||
|
||
Формат записи, меты, слага, индекса и `REJECTED.md` —
|
||
[references/task-format.md](references/task-format.md); там же тест «готова к
|
||
взятию». Схема и алгоритм каждого типа — по файлу на тип:
|
||
[feature](references/task-feature.md) ·
|
||
[fix](references/task-fix.md) · [chore](references/task-chore.md) ·
|
||
[research](references/task-research.md).
|
||
|
||
## Версия раскладки
|
||
|
||
Формат каталога задач меняется, и проект должен знать, к какой версии он
|
||
приведён. Число живёт ключом `version` в `.av-dev.toml` в корне репозитория,
|
||
журнал версий — [журнал скилла `canon`](../canon/references/changelog.md),
|
||
сверяет их `tasks.py check`: отстало — строка расхождения, ушло вперёд — устарел
|
||
плагин. Обратной совместимости нет: есть «приведён» и «не приведён».
|
||
|
||
**Версия одна на всю раскладку — и на документы, и на задачи.** Своя у каталога
|
||
задач была, пока плагинов было три и ставились они порознь: проект мог взять
|
||
учёт работ без канона документов, и общее число оказалось бы домом, которого у
|
||
половины проектов нет. Плагин один — довод ушёл, а два числа оставляли бы
|
||
вопрос, по какому журналу повышать.
|
||
|
||
**Повышает проект скилл `av-dev:canon`, операция `upgrade`** — он идёт по
|
||
журналу, двигает число и зовёт этот скилл там, где запись касается задач. Здесь
|
||
повышения нет намеренно: две операции, двигающие одно число, разъезжаются на
|
||
первом же проекте, где прошла только одна из них.
|
||
|
||
## Сценарии
|
||
|
||
### Завести запись из диалога
|
||
|
||
0. **Посмотри стадию** — `stage`. От неё зависят шаг 1 и место новой строки: на
|
||
доработке беклог пополняют по одной и с фильтром, на стройке пишут планом.
|
||
1. **Фильтр — на доработке.** Делаем прямо сейчас — не заводим. Не пожалеем о
|
||
потере — не заводим. Родилось три кандидата — покажи их и спроси, какие
|
||
заводить: молча заведённая пачка и есть тот самый отказ из правила 1.
|
||
**На стройке фильтра нет**: план пишется вперёд целиком, и «этого мы сейчас
|
||
не делаем» — не довод против шага, а описание всякого шага, кроме первого.
|
||
2. **Дедуп.** `list` плюс поиск по слагам, полю «зачем» и телам (`grep -ril`),
|
||
**включая `REJECTED.md`**. Нашлось среди живых — **дописываем в существующий
|
||
файл**, а не заводим соседний. Нашлось в `REJECTED.md` — покажи пользователю
|
||
ту строку и что изменилось с момента отказа (`add` предупредит и сам, но
|
||
молча заводить нельзя). Две задачи об одном — самая дорогая находка
|
||
переоценки.
|
||
3. **Тип** — `--type` обязателен, и он же первое содержательное решение:
|
||
|
||
- снаружи появляется то, чего не было → `feature`;
|
||
- поведение расходится с заявленным и **воспроизводится** → `fix`
|
||
(не воспроизводится → `research`);
|
||
- обслуживание, наблюдаемое поведение не меняется → `chore`;
|
||
- исход — знание, а не изменение системы → `research`.
|
||
|
||
Не подходит ни один — в записи их два, разбирай. Не проходит тест готовности
|
||
(см. task-format) — это **сырьё**: `--type research`, раздел «Вопрос» пока
|
||
пуст, место в конце секции. Не делается одним заходом — дроби на шаги
|
||
помельче и ставь их в списке подряд.
|
||
4. **Место в списке.** `add` кладёт строку в конец секции всегда. На стройке это
|
||
почти наверняка не то место: порядок там зависимость, и новый шаг чаще всего
|
||
встаёт в середину — `move <слаг> --after <слаг>`. На доработке конец списка
|
||
законен: место в очереди назначает груминг, а не заведение.
|
||
5. `add …`, затем допиши тело редактором **по схеме своего типа** — шаблон её
|
||
уже разложил, устав типа объясняет каждый раздел. «Зачем» отвечает «зачем
|
||
нужна эта задача» — состояние, остаток, боль, — а не пересказывает первый
|
||
абзац, и пишется **для человека**: не «канонизация внутри транзакции», а
|
||
«тело 40 МиБ держит блокировку 5 секунд, соседние доставки уходят в отказ».
|
||
6. `check`.
|
||
|
||
### Разобрать находки аудита или ревью
|
||
|
||
Ревью и аудиты — тоже источник задач, но с опасностью, зеркальной диалогу: не
|
||
пять файлов из одной мысли, а сорок файлов из сорока сырых находок. Защита та
|
||
же, что в самом ревью: кластеризация по причине, дедуп против живых и
|
||
`REJECTED.md`, находка без свидетельства → сырьё (`research`), а не задача, и карта кластеров
|
||
пользователю до создания файлов. **Стадию смотри и здесь**, тем же нулевым
|
||
шагом: от неё зависит, куда ляжет тяжёлая находка — наверх очереди или после
|
||
своей зависимости. Порядок и отображение серьёзности —
|
||
[references/from-review.md](references/from-review.md).
|
||
|
||
### Прийти в репозиторий, где задачи уже как-то ведутся
|
||
|
||
Разовая операция: вывести каталог задач из старой раскладки беклога, `TODO.md`,
|
||
заметок или списка шагов плана — [references/adopt.md](references/adopt.md).
|
||
Сюда же относится переименование транслитных слагов в английские: оно делается
|
||
**одним проходом вместе с починкой перекрёстных ссылок**, а не по одному слагу.
|
||
|
||
Если переводить надо не только задачи, а весь `docs/` — это скилл
|
||
`av-dev:canon`, и он зовёт этот сценарий сам на своём шаге.
|
||
|
||
### Пересмотр плана стройки
|
||
|
||
Операция стадии `build`, и на доработке её нет: там переоценка идёт порциями и
|
||
называется грумингом. **Повод один — сменился замысел**, а не «давно не
|
||
смотрели»: план стройки протухает не по частям, а целиком, потому что порядок в
|
||
нём — зависимость, и одна изменившаяся посылка переставляет всё, что ниже.
|
||
|
||
Порционный разбор здесь вреден, и это не вкус: вынуть пять шагов из середины
|
||
списка, порядок которого и есть его содержание, — значит получить план, про
|
||
который никто уже не скажет, почему он такой.
|
||
|
||
1. **Назови, что изменилось в замысле.** Одной фразой, и она уедет причиной в
|
||
каждое движение. Не находится — значит повода нет, и пересмотр не нужен.
|
||
2. **Прочитай список целиком**, сверху вниз, и по каждой строке ответь одно из
|
||
трёх: остаётся как есть, переезжает (`move --after` с причиной), уходит
|
||
(`close --reason`). Дописанное новое встаёт туда, куда велит зависимость, а
|
||
не в конец.
|
||
3. **Покажи человеку весь новый список**, а не отдельные решения: план читается
|
||
только целиком. `AskUserQuestion` с готовым порядком и доводом на каждое
|
||
движение.
|
||
4. `check` и доклад: сколько строк тронуто из скольких, что ушло и почему.
|
||
|
||
**Границу с грумингом держи твёрдо.** Если хочется пересмотреть план «потому что
|
||
накопилось» — это не пересмотр, а признак того, что стройка кончилась: беклог
|
||
перестал быть планом и стал очередью. Проверь `stage`.
|
||
|
||
### Декомпозиция и штурм сырья
|
||
|
||
[references/split.md](references/split.md). Обе операции превращают одну запись в
|
||
несколько, и у обеих есть проверяемый тест: части должны **мерджиться порознь** и
|
||
**каждая давать видимую пользу**, а у штурма исход «выкинуть» — полноправный.
|
||
|
||
Там же **шов**: где резать, когда допустимых мест несколько. Коротко — по
|
||
границе, где **меняется род работы**; и резать пореже, потому что костяк ревью
|
||
разрез удваивает **всегда** — состав прогона постоянный и от размера половин не
|
||
зависит. Выигрыш даёт не проверка, а то, что половина доводится и мерджится сама.
|
||
|
||
### Вычитка: два прохода, а не один
|
||
|
||
Записи судит **не тот агент, который их написал**: самопроверка текста слабее
|
||
всего ровно там, где формулировка казалась удачной при написании. Проходов два,
|
||
и они разные по природе:
|
||
|
||
| Проход | Что смотрит | Над чем работает |
|
||
| --- | --- | --- |
|
||
| `task-form` | заголовок по типу, «зачем» вместо пересказа, границы вместо замысла, годность оракулов, предписание процесса | только `items/` |
|
||
| `task-wording` | залог и отглагольные, оценка без факта, стоп-слова, англицизмы, жаргон, неизвестный термин, транслит в слаге | `items/` и строки индекса; документы проекта — только как словарь |
|
||
|
||
Разделены они не по охвату, а **по глубине**. Язык проверяется по словам и
|
||
фразам, поштучно; форма записи требует понять, что задача делает. Слитый проход
|
||
одну половину делает дорогой, а вторую — поверхностной.
|
||
|
||
Модель у обоих одна, `sonnet`, и это не отменяет разреза. Оба судят по
|
||
**записанному правилу** — шесть пунктов формы против правил языка, — а их находка
|
||
приходит готовой формулировкой, которую читает и отклоняет человек, а не молча
|
||
реализует оркестратор. Ошибка здесь стоит строки чтения, и платить за неё верхней
|
||
моделью не за что.
|
||
|
||
Каждый устав отказывается от чужой половины прямо: увиденное не по своей части
|
||
идёт **строкой в границах покрытия**, а не находкой. Две проверки одного места
|
||
расходятся и начинают спорить, и разнимать их потом дороже, чем не сводить.
|
||
|
||
**Порядок — сперва `task-form`.** Его находки меняют решение «брать или не
|
||
брать», а язык — только цену чтения; и переписанный заголовок бессмысленно
|
||
вычитывать до того, как он переписан.
|
||
|
||
Зовутся они **пачкой, а не на каждую запись**: после заведения нескольких задач,
|
||
после разбора находок ревью, после того как чужая работа уточнила записи (так
|
||
делает разведка в `av-dev:code-resolve`), и на переоценке. Передаётся список файлов и — если
|
||
есть — паспорт, архитектура и конвенции проекта: по ним отличается неизвестный
|
||
термин от известного.
|
||
|
||
Ни один из них ничего не правит. Оба возвращают готовые формулировки, и их
|
||
подставляет скилл: заголовок — `edit <слаг> --title …`, «зачем» —
|
||
`edit <слаг> --why …`, остальное редактором. **Заголовок и «зачем» — это то, по
|
||
чему задачу выбирают, поэтому менять их молча нельзя**: покажи предложенное
|
||
пользователю вместе с тем, что было. Правки в теле (границы, критерии, язык)
|
||
применяются сразу.
|
||
|
||
Всё, что ловит `tasks.py check`, оба не трогают намеренно.
|
||
|
||
### Гигиена полей
|
||
|
||
Правится по ходу любой операции, которая задачи касается (но не «заодно» по
|
||
всему беклогу):
|
||
|
||
- **протухшее «зачем»** — задача изменилась, а поле отвечает на старый вопрос;
|
||
особенно после ответа на вопрос задачи: «Решено: …» на «почему это лежит в
|
||
беклоге» уже не отвечает. Переписывается `edit <slug> --why …` — он правит
|
||
мету файла и строку индекса заодно;
|
||
- **вопрос, застрявший в прозе** — вынимается в раздел «Вопросы» плюс тег
|
||
`question` (`edit --add-tag question`), иначе он не виден ни `list
|
||
--questions`, ни правилу «задача с открытым вопросом в работу не берётся»;
|
||
- **тег, который некому снять** — `question` после ответа снимается `edit
|
||
--rm-tag question` вместе с записью ответа в тело **и опустошением раздела
|
||
«Вопросы»**: судит раздел, а не тег (`references/task-format.md`);
|
||
- **свойство репозитория в рамках** — номер миграции, хеш, версия зависимости:
|
||
в лежалой задаче протухает молча и становится ложной рамкой. Снимается;
|
||
снимок берётся при постановке, а не при заведении;
|
||
- **предписание процесса в теле** — «прогнать глубоким ревью», «взять такой-то
|
||
агент», «этой задаче хватит короткой проверки»: это второй дом для правила
|
||
выбора и путь понизить требования решением, принятым до проектирования.
|
||
Снимается;
|
||
- **тип, разошедшийся с задачей** — задача заводилась починкой, а после разбора
|
||
оказалось, что поведение никогда и не было заявлено: это `feature`, а не `fix`.
|
||
Правится `edit <slug> --type …`; тип, оставшийся от прошлой формулировки, врёт
|
||
ровно там, где по нему отбирают, **и требует не тех разделов**: у брошенного
|
||
`fix` останется «Воспроизведение», которого нечем заполнить;
|
||
- **сырьё, у которого появился вопрос** — разведка обросла формулировкой, но
|
||
раздел «Вопрос» так и пуст: она числится сырьём и в работу не берётся.
|
||
Записывается вопрос, и `check --fix` поднимает строку из конца категории;
|
||
- **границы, названные вместо реализации** — «переписать хранилище на новый
|
||
драйвер» в разделе «Затрагивает» это не граница, а замысел. Границы —
|
||
`таблица points и её миграция`, `эндпоинт POST /ingest`, `формат отпечатка на
|
||
диске`. Переписывается перечнем;
|
||
- **англицизм и термин из ниоткуда** — правится по ходу той же операции, что
|
||
касается задачи (см. «Как написана задача»). Именно по ходу: беклог не
|
||
переписывают ради языка.
|
||
|
||
## Переносимость
|
||
|
||
Скилл независим от **языка программирования, сборки, CI и трекера**: он ничего
|
||
не знает ни про Go, ни про npm, ни про конкретный багтрекер — задачи для него
|
||
просто каталог markdown. Текст задач — русский (язык документации проекта);
|
||
зашита только латиница слага. OpenSpec ему тоже не нужен.
|
||
|
||
- **Каталог задач — `tasks/` в корне, жёстко**, и `--dir` передаётся явно всегда:
|
||
раскладка канона одинакова во всех проектах, и искать больше нечего. Каталога
|
||
нет — код 3 и вопрос человеку; `init` заводит его **только** когда проект
|
||
действительно новый, а перевод чужой раскладки делает `av-dev:canon`.
|
||
У скрипта поиск вверх по дереву ещё жив — он для непереведённых проектов, и
|
||
полагаться на него скилл не должен: молча найденный чужой каталог это дрейф.
|
||
- **Версия и настройки живут в `.av-dev.toml` в корне репозитория** — версия
|
||
ключом `version`, настройки каталога секцией `[tasks]`: `dir` — где каталог
|
||
лежит, `stage` — стадия проекта, плюс **имена** файлов и заголовков, и
|
||
последние только если отличаются от умолчания. Неизвестный ключ в секции — код
|
||
3 на любой команде, так что лишнее слово останавливает работу с задачами
|
||
целиком.
|
||
|
||
Дом в корне, а не внутри каталога задач, по двум причинам: настройка, лежащая
|
||
внутри настраиваемого каталога, не смогла бы сказать, **где он**; и версия
|
||
одна на весь плагин, а корень есть и у проекта без `docs/`. Прежние
|
||
`<каталог задач>/.tasks.json` и `docs/.docs.json` не читаются — увидев их,
|
||
скрипт говорит «прежняя раскладка» и зовёт `upgrade`.
|
||
- **Секции беклога** берутся из заголовков `##` индекса как есть; их названия —
|
||
дело проекта (умолчание `План` на стройке, `Ядро` / `Инфра` на доработке), а
|
||
количество ограничено стадией: на стройке секция одна. **В конфиге секций
|
||
нет** — второй список разошёлся бы с заголовками молча.
|
||
|
||
### Вызов из другого плагина
|
||
|
||
`$CLAUDE_PLUGIN_ROOT` раскрывается **только внутри своего плагина**: конвейер
|
||
задачи, конвейер ревью и любой другой чужой контекст до `tasks.py` по этой
|
||
переменной не дотянутся. Мост — **вызов скилла через пространство имён**, а не
|
||
путь:
|
||
|
||
> Чужой контекст зовёт `Skill av-dev:task-track` и называет, что нужно сделать
|
||
> («закрой задачу `<слаг>`, реализована»). Скилл разрешает свой
|
||
> `$CLAUDE_PLUGIN_ROOT` сам. Путь наружу не выносится вовсе.
|
||
|
||
Каталога задач в проекте нет — вызывающий **не выдумывает путь и не правит
|
||
индекс руками**, а сообщает в докладе, что учёт остаётся за владельцем. Скилл
|
||
при этом разрешится: он в том же плагине, что и вызывающий.
|
||
|
||
## Слоты проекта
|
||
|
||
Почти всё, что скиллу нужно знать о проекте, отвечает канон структурой: куда
|
||
переезжает суть реализованной задачи — `openspec/specs`, `adr/`, архив change;
|
||
какие в проекте оракулы — семантика гейта в `CLAUDE.md`. Отдельными слотами
|
||
остаётся то, чего из раскладки не вывести. **Проект дописывает в `CLAUDE.md`**:
|
||
|
||
1. **Что такое «сделана»** — чем задача выполняется (конвейер проекта) и что
|
||
входит в его определение сделанного. Скилл требует лишь **форму**: конвейер
|
||
проекта пройден + критерии приёмки проверены поимённо.
|
||
2. **Что считается необратимым** и потому спрашивается у человека всегда
|
||
(деплой, выкладка наружу, удаление или перезапись данных).
|
||
|
||
Ни того ни другого скилл не угадывает: не нашёл — спрашивает пользователя, а не
|
||
подставляет умолчание.
|
||
|
||
## Общее для всех сценариев
|
||
|
||
- **Развилки — пользователю.** Через `AskUserQuestion`, с уже сформулированным
|
||
предварительным суждением (**рекомендация — первым вариантом**). Что выкинуть,
|
||
какая рамка разведки верна, пора ли менять стадию — решение пользователя. Слаг
|
||
и формулировка — механика, делаем сами. **Порядок строк механикой не
|
||
считается** ни на одной стадии: на стройке он зависимость, на доработке
|
||
приоритет, и оба называет человек.
|
||
- **Не больше трёх вопросов за раз.** Пачка длиннее трёх тяжела для ответа;
|
||
решений больше — веди **несколько итераций** диалога по ≤3, а не один
|
||
перегруженный запрос. Между итерациями применяй уже решённое.
|
||
- **Границы покрытия в отчёте.** Любая сессия разбора, штурма или заведения записей
|
||
заканчивается строкой «просмотрено N из M, не трогали — …». Отчёт без неё
|
||
сообщает «беклог разобран», не сообщая, какая его часть осталась нетронутой.
|
||
- **Ничего не удаляем молча.** Файл исчезает только через `close` — `--reason`
|
||
(ушла без реализации) или `--implemented` (реализована). Прямого `rm` нет.
|
||
- **Слаги английские**, kebab-case, не транслит: `tie-break-equal-completeness`,
|
||
а не `taj-brejk-pri-ravnoj-polnote`. Заголовки, тела и «зачем» — русские.
|
||
|
||
## Чего этот скилл не делает
|
||
|
||
Не пишет код, не заводит спеки и предложения об изменении, не берёт задачу в
|
||
работу — этим занимается конвейер проекта. **Не ведёт очередь:** что делать
|
||
следующим и что перестало быть важным — скилл `task-groom`, а этот даёт ему операции.
|
||
Не решает за пользователя, что важно. Не
|
||
переоформляет существующие задачи «заодно»: правится то, чего касается операция.
|