Пара плагинов с намеренно проведённой границей: av-dev-tasks отвечает за то, что делаем и в каком порядке, av-dev-pipeline — за то, как ведём одну задачу. Зависимости между ними нет: управление задачами работает и с ручным исполнением, пайплайн — на проекте с любым учётом задач. - av-dev-tasks — преемник av-dev-backlog: цели вместо приоритетов, спринт под одну цель с заморозкой набора, различение вопроса и блокера, каденция «вопросы — разбор — переоценка — набор». Раскладка docs/tasks с items/, PLAN.md, BACKLOG.md, SPRINT.md, REJECTED.md; проверенное из av-dev-backlog перенесено, не переписано. - av-dev-pipeline — вынос того, что лежало копиями в healthlog и jellybit (3628 строк) и уже разошлось: цикл SDD, конвейер ревью с обязательным триажем, прогон нескольких задач разом. Проектная специфика вынесена в файл-бриф, charter'ы несут метод. Коммит фиксирует состояние на момент ревью: три прохода нашли блокирующие дефекты (нет шага, заводящего бриф; git rebase на занятой worktree ветке; sprint drop пишет наполовину) — они чинятся следующими коммитами. Сохранено как база, от которой видно правки.
204 lines
14 KiB
Markdown
204 lines
14 KiB
Markdown
# Формат задач, целей и индексов
|
||
|
||
Заголовок, мета-строку и строку индекса ставит `tasks.py add` — руками их не
|
||
пишут. Этот файл описывает, что именно скрипт создаёт и что проверяет `check`;
|
||
тело задачи (одну фразу, критерии, рамки, контекст) дописывает агент.
|
||
|
||
## Файл задачи
|
||
|
||
`items/<slug>.md`:
|
||
|
||
```markdown
|
||
# Тай-брейк при равной полноте
|
||
|
||
**Секция:** ядро — вышла из спринта: остаток писал нерешённое в журнал · **Теги:** goal:merge-robustness, sprint:2026-08
|
||
|
||
При столкновении точек выигрывает более полная, но при равной полноте побеждает
|
||
последняя доставка — а она систематически беднее первой.
|
||
|
||
## Критерии приёмки
|
||
|
||
- повторный прогон свёртки даёт тот же отпечаток состояния — оракул: команда сверки
|
||
- накопительная метрика за сутки не уменьшается после повторной доставки — оракул: тест
|
||
- в логе видно, какая из двух точек выиграла и почему — оракул: глазами по логу прогона
|
||
|
||
## Рамки
|
||
|
||
Схема не трогается; данные только читаются; перезапуск сервиса допустим.
|
||
|
||
Связано: решение о канонической форме содержимого.
|
||
```
|
||
|
||
- **Заголовок H1** — он же заголовок строки в индексе, дословно. Тип кодируется
|
||
префиксом `[goal]` / `[idea]` / `[epic]`; обычная задача — без префикса.
|
||
Отдельного поля типа **нет**: два места для одного факта разъезжаются, а
|
||
префикс виден прямо в индексе, где и принимается решение «брать или не брать».
|
||
- **Мета-строка** — первая непустая строка после заголовка. Обязательна секция,
|
||
причина после тире желательна (именно она объясняет, почему задача здесь
|
||
оказалась — в том числе «вышла из спринта: …»), теги опциональны. Поля
|
||
разделяются ` · `, порядок свободный. `·` — служебный разделитель: в тексте
|
||
причины его быть не должно.
|
||
- **Тело** — одна фраза «что станет наблюдаемо иначе», критерии приёмки, рамки,
|
||
контекст, ссылки. Пишется на языке документации проекта.
|
||
|
||
Тело — не план реализации и не спецификация: принятое и реализованное переезжает
|
||
в документацию проекта, а файл задачи удаляется.
|
||
|
||
### Критерии приёмки
|
||
|
||
2–5 проверяемых утверждений, **у каждого назван оракул**. Не «работает
|
||
корректно», а «повторный прогон даёт тот же отпечаток — оракул: команда сверки».
|
||
Это не второе определение готовности, а проектная конкретизация вопроса «по чему
|
||
видно, что закончено» из теста готовности ниже: там сказано «признак
|
||
завершённости», здесь — «признак плюс чем проверяется».
|
||
|
||
**У идей критериев нет — именно поэтому они идеи.**
|
||
|
||
**Критерии — пол, но расхождение с ними есть дефект критериев.** Если приёмщик
|
||
видит, что критерии закрыты, а суть задачи не достигнута, он **правит критерии и
|
||
возвращает задачу исполнителю**, а не держит невидимое сверх-требование. Иначе
|
||
исполнитель никогда не знает, закончил ли, и мотивирован занижать критерии
|
||
заранее.
|
||
|
||
### Рамки
|
||
|
||
Одна строка: чего касаться нельзя, что перезапускается, что считается
|
||
необратимым, трогается ли схема данных. **Свойства репозитория сюда не пишутся**
|
||
— номер последней миграции, версия зависимости, хеш: в лежалой задаче они
|
||
протухают молча и становятся ложной рамкой. Снимок берётся при постановке, а не
|
||
при заведении.
|
||
|
||
### Вопросы
|
||
|
||
Неразобранное решение человека живёт разделом `## Вопросы` **плюс тегом
|
||
`question`**. Тег — то, по чему вопрос виден снаружи файла (`list --questions`) и
|
||
чем работает правило «задача с открытым вопросом в набор не берётся». Раздел без
|
||
тега или тег без раздела — дрейф, `check` о нём скажет.
|
||
|
||
Ответ записывается в тело, тег снимается `edit <slug> --rm-tag question`, а хук
|
||
переписывается: «Решено: …» на вопрос «почему это лежит в беклоге» уже не
|
||
отвечает.
|
||
|
||
## Файл цели
|
||
|
||
```markdown
|
||
# [goal] Прочность слияния
|
||
|
||
**Секция:** кусты · **Теги:** decomposed
|
||
|
||
Ради чего: точки из разных доставок сходятся в один часовой объект, и сегодня
|
||
исход столкновения зависит от порядка доставки, а не от содержания.
|
||
|
||
## Завершение
|
||
|
||
Достигнута, когда исход слияния не зависит ни от порядка, ни от времени
|
||
доставки, и это подтверждено повторным прогоном на живом корпусе.
|
||
```
|
||
|
||
- **Задачи цели здесь не перечисляются.** Перечень даёт
|
||
`tasks.py list --goal <слаг>`; хранимый список стал бы третьим индексом и
|
||
поехал бы на первой же закрытой задаче.
|
||
- **Раздел «Завершение»** — то, по чему видно, что цель достигнута. Он же
|
||
отличает «цель ещё не декомпозирована» от «все её задачи закрыты»: пометка
|
||
вроде тега `decomposed` или строки в теле ставится, когда цель разложена на
|
||
задачи.
|
||
- Цель живёт в `PLAN.md` и **никогда** — в `BACKLOG.md` или `SPRINT.md`.
|
||
|
||
## Слаг
|
||
|
||
Латиница и цифры, kebab-case, без ведущих, хвостовых и двойных дефисов
|
||
(`foo-bar`, не `-foo`, `a--b`). Именуется **по сути, а не по текущей
|
||
формулировке**: заголовок будет переписан при переоценке, а слаг стоит в ссылках
|
||
из других задач, коммитов и черновиков. **Транслита не заводим** —
|
||
`tie-break-equal-completeness`, а не `taj-brejk-pri-ravnoj-polnote`: транслит
|
||
нечитаем для того, кто ищет по смыслу, и не сокращается.
|
||
|
||
Переименование слага — не правка, а перенос ссылок: делается одним атомарным
|
||
проходом по всем местам, где слаг упомянут, иначе останутся битые ссылки,
|
||
которых никто не проверяет.
|
||
|
||
## Индексы
|
||
|
||
Строка везде одной формы:
|
||
|
||
```markdown
|
||
- [Заголовок дословно](items/slug.md) — хук
|
||
```
|
||
|
||
Хук отвечает на «почему это лежит в беклоге» одним предложением: состояние,
|
||
остаток, боль. Пересказ первого абзаца бесполезен — он уже есть по ссылке.
|
||
|
||
| Файл | Что отвечает | Секции |
|
||
| --- | --- | --- |
|
||
| `PLAN.md` | какие есть цели, в каком порядке идёт линия и почему | линия (упорядоченная) и кусты |
|
||
| `BACKLOG.md` | что **можно взять** — только задачи | секции проекта (по умолчанию ядро/инфра) |
|
||
| `SPRINT.md` | какая цель и какой набор под неё | одна: «Набор» |
|
||
| `REJECTED.md` | что ушло без реализации и почему | — |
|
||
|
||
Секции — **единственные заголовки `##` в индексе**: любой другой `##` в
|
||
преамбуле проверка сочтёт секцией. Внутри секции беклога порядок значения не
|
||
имеет — порядка в беклоге нет вовсе. В **линии** плана порядок значим и
|
||
обосновывается прозой; двигают строку `move <slug> --section линия --after
|
||
<другой>`.
|
||
|
||
Индексы **производны**: расходятся с файлом — правим индексы (`check --fix`).
|
||
Строку руками не пишут.
|
||
|
||
`SPRINT.md` и есть артефакт заморозки: без него набор существует только в
|
||
контексте сессии, и нарушение заморозки ненаблюдаемо.
|
||
|
||
## `REJECTED.md`
|
||
|
||
Туда уходит задача, покинувшая беклог **без реализации**. Строку пишет
|
||
`tasks.py close --reason`, а `check` следит за форматом:
|
||
|
||
```markdown
|
||
- 2026-07-23 `versii-kachestvo-repaki` — Версии и качество одного тайтла.
|
||
Причина: калибровка болей — не боль, ни разу не возникло за полгода.
|
||
Была секция: инфра.
|
||
```
|
||
|
||
Реализованные сюда не попадают: у них остаётся коммит и документация. У
|
||
выкинутой не остаётся ничего — и через квартал она возвращается тем же текстом.
|
||
Это первое место, куда смотрит дедупликация при заведении.
|
||
|
||
Запись не запрещает завести задачу заново: изменился контекст — заводим и
|
||
ссылаемся на строку, объясняя, что изменилось.
|
||
|
||
## Теги
|
||
|
||
Единственный механизм разметки, потому что `list --tag` уже умеет отбирать по
|
||
ним порцию разбора. Отдельных полей мета-строки под это не заводим.
|
||
|
||
- `goal:<слаг>` — цель, которой служит задача. Обязателен: задача без цели не
|
||
попадёт ни в один спринт.
|
||
- `question` — в файле есть неразобранный раздел «Вопросы».
|
||
- `sprint:<слаг>` — задача заведена в этом спринте; по нему отбирается первая
|
||
порция разбора («урожай спринта»).
|
||
|
||
Свои теги проект заводит свободно (партия ревью `review-ГГГГ-ММ-ДД`, тема,
|
||
источник) — словарь не фиксирован. В индексы теги не выносим: индексы
|
||
производны, отбор делает `list --tag`, а не глаза.
|
||
|
||
## Тест «готова к взятию»
|
||
|
||
Задача готова, если из файла отвечаются три вопроса:
|
||
|
||
1. **Что станет наблюдаемо иначе**, когда она сделана — снаружи: пользователю,
|
||
владельцу сервиса или разработчику. «Отрефакторить X» — не ответ; «перестанет
|
||
ломаться Y при Z» — ответ.
|
||
2. **По чему видно, что закончено** — критерии приёмки с оракулами.
|
||
3. **Какой цели она служит** — тег `goal:` и одна строка «почему именно этой».
|
||
|
||
Не отвечается первый или второй вопрос → это **идея** (`[idea]`), её место в
|
||
штурме. Не отвечается третий → либо цель есть и не проставлена, либо задача не
|
||
служит ничему — тогда её не надо заводить.
|
||
|
||
Отвечается всё, но задача не делается одним заходом и не мерджится целиком →
|
||
**эпик** (`[epic]`), сперва декомпозиция. Эпик временен и исчезает после
|
||
разбора; цель (`[goal]`) постоянна — не путать.
|
||
|
||
Тест применяется при заведении и при переоценке. К старым задачам, которых
|
||
операция не касается, задним числом не применяется — беклог не переоформляют
|
||
«заодно».
|