канон 4: тип записи стал единственной осью и задаёт схему

Осей было две — тип записи (goal/idea/task) и род работы (kind:<род>
тегом), — и ортогональность у них была фальшивой: из двенадцати клеток
произведения законны шесть. У цели род запрещён, у задачи обязателен, у
идеи пуст и на практике не ставится. Плюс «алгоритм работы над записью
такого типа» крепится не к task, а к fix и research, то есть к роду:
ось, к которой пишется алгоритм, и была настоящим типом. Схлопнуто в
одну ось из пяти значений: goal | feature | fix | chore | research.

Тип idea упразднён отдельно и по другой причине: он значил не род
работы, а незаполненность, а состояние типом быть не может — оно
меняется по мере того, как запись дописывают, а тип меняют командой.
Теперь состояние выводится из заполненности: research без раздела
«Вопрос» это сырьё. В спринт не берётся, как и прежняя идея, лежит в
конце категории, отбирается list --raw.

Дом типа — поле меты «Тип» первой строкой, эмодзи в H1 производна.
Прежнее «отдельного поля типа нет: два места для одного факта
разъезжаются» отменено собственным аргументом: он был против префикса
плюс поля, а при переносе дома место остаётся одно. Эмодзи стоит в H1,
а не в строке индекса, чтобы инвариант «заголовок в индексе дословно»
остался нетронутым.

Поле места названо по типу: «Секция» у цели (часть роадмапа, состояние
очереди), «Категория» у задачи (полка домена, куда её вернёт sprint
drop). Одинаковое переименование закрепило бы конфляцию; какое поле
обязательно, решает тип — то самое, ради чего затевалась правка.

Два новых обязательных раздела выросли из правил, которые были записаны
и которые нечем было проверить. «Не воспроизводится — это research, а не
fix» стояло в каноне: теперь есть раздел «Воспроизведение». Приёмка
разведки — «записанный ответ, а не изменённый код» — тоже стояла, но
sprint take требовал от research два-пять критериев с оракулами, и они
писались ради проверки; вместо них «Вопрос» и «Куда ляжет ответ».

Сортировка «по важности» из заметок не взята: она требует, чтобы кто-то
важность поддерживал, а это приоритет, от которого отказалось правило 4.
Взято только «сырьё в конец категории» — этот порядок выводится из типа
и заполненности, а не назначается человеком, и потому проверяется
машиной.

TYPE_SCHEMA кормит и body_template, и schema_verdict: иначе add кладёт
то, на чём sprint take потом откажет. check --fix мигрирует за один
проход — kind:/[goal]/[idea] в поле «Тип», эмодзи в заголовок, «Секция»
→ «Категория», сырьё в конец. Тип, которого неоткуда взять, не
угадывается: feature от chore машина не отличает, такие записи уходят в
НЕОДНОЗНАЧНО поимённо.

Попутно закрыт класс отказов в --fix: шагов, правящих мету, стало пять,
и второй, перечитавший файл с диска, стирал правку первого. Общий
stage() поверх отложенных правок; до этого корректность держалась на том,
что шагов было мало.

Устав на тип отдельным файлом — references/task-<тип>.md, пять штук:
схема, алгоритм, что видит машина и что человек. Агент task-form получил
правило «тип сходится с тем, что в записи написано» с проверяемыми
расхождениями.

Обкатано на демо-наборе из 13 записей: миграция за один проход, второй
прогон даёт ноль починок; fix без «Воспроизведения» и сырьё в спринт не
идут, годная feature берётся.

DECISIONS тема 27 (ААББ–ЛЛММ, следствия 101–104).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-08-05 10:00:05 +03:00
co-authored by Claude Opus 5
parent 069205ac69
commit 228b6c7eee
18 changed files with 1521 additions and 511 deletions
+153 -114
View File
@@ -1,19 +1,19 @@
---
name: tasks
description: Ведение задач и целей как каталога markdown-файлов (одна запись = один файл в items/ + строка в одном из индексов). Заведение задачи, идеи или цели из диалога, разбор находок аудита/ревью, декомпозиция на независимо полезные части, мозговой штурм идеи, гигиена полей и проверка согласованности индексов. Использовать, когда просят добавить задачу/идею/цель, превратить находки ревью в задачи, разбить задачу, проработать идею, поправить формат или проверить беклог. Ритуал между спринтами — скилл session. Не реализует задачи — этим занимается пайплайн проекта.
description: Ведение задач и целей как каталога markdown-файлов (одна запись = один файл в items/ + строка в одном из индексов). У каждой записи есть тип (goal, feature, fix, chore, research), и тип решает, каких разделов она требует и что с ней можно делать. Заведение записи из диалога, разбор находок аудита/ревью, декомпозиция на независимо полезные части, штурм сырья, гигиена полей и проверка согласованности индексов. Использовать, когда просят добавить задачу/идею/цель, превратить находки ревью в задачи, разбить задачу, проработать идею, поправить формат или проверить беклог. Ритуал между спринтами — скилл session. Не реализует задачи — этим занимается пайплайн проекта.
---
# Задачи
Задачи — каталог markdown-файлов. Одна запись = один файл `items/<slug>.md` плюс
строка **ровно в одном** индексе. Скилл владеет **форматом и содержимым**:
заводит, редактирует, закрывает, разбирает находки ревью, дробит, штурмует идеи.
заводит, редактирует, закрывает, разбирает находки ревью, дробит, штурмует сырьё.
Чем он **не** владеет: ритуалом между спринтами (разбор вопросов → разбор
прошедшего спринта → переоценка → выбор цели и набор) — это скилл `session`; и
выполнением задачи — это пайплайн проекта.
## Пять правил, из которых всё следует
## Шесть правил, из которых всё следует
Ситуация не покрыта инструкцией — решай по ним.
@@ -43,10 +43,20 @@ description: Ведение задач и целей как каталога mar
4. **Порядка нет, есть цель — но цель есть не у всякой задачи.** Приоритетов,
«повысить» и «встать раньше» нет: «что делать дальше» отвечает набор спринта,
а между спринтами порядок не нужен никому. Цель обязательна там, где она и
есть содержание работы, — у **новой возможности** (`kind:feature`). Починка,
есть содержание работы, — у **новой возможности** (`feature`). Починка,
техдолг и разведка служат работоспособности, а не направлению, и живут без
цели законно; в набор спринта они входят помимо его цели. Придуманная им цель
— то же враньё, от которого спасает род работы.
— то же враньё, от которого спасает тип.
Единственный порядок, который в беклоге всё-таки есть, **производен от типа**,
а не назначен человеком: **сырьё** (`research` без раздела «Вопрос») стоит в
конце своей категории. Его не берут, и между берущимся оно каждый раз требует
открыть файл, чтобы это понять. Раз порядок выводится, его проверяет машина —
и приоритетом он не становится.
5. **Тип решает, что с записью можно делать.** Тип — единственная ось и первое
поле меты: от него зависят обязательные разделы тела, нужна ли цель, берётся
ли запись в спринт и в каком индексе живёт её строка. Словарь закрыт; ни один
тип не подошёл — значит, в записи их два, и её надо разделить.
## Раскладка
@@ -82,10 +92,12 @@ docs/tasks/
открывают чаще всего, — что делается сейчас и что дальше. Порядок проверяет
`check`, переставляет `check --fix`.
**Секции роадмапа канонические, секции беклога — нет**, и разница не в любви к
**Секции роадмапа канонические, категории беклога — нет**, и разница не в любви к
единообразию. У каждой секции роадмапа свой смысл, в достигнутое пишет сам `close`, и
роадмап, названный по-своему, читался бы только своим автором. Секции беклога
(`Ядро`, `Инфра`) смысла не несут — это полки, и остаются делом проекта.
роадмап, названный по-своему, читался бы только своим автором. Категории беклога
(`Ядро`, `Инфра`) смысла не несут — это полки домена, и остаются делом проекта.
Отсюда и разные имена поля меты: у цели **Секция** (часть роадмапа — состояние
очереди), у задачи **Категория** (полка, в которую она вернётся из спринта).
Отсюда четыре правила, которые проверяет `tasks.py check`: **состав закреплён**
(чужая секция — ошибка, а не вольность), **все четыре обязаны быть** (нет
@@ -93,7 +105,7 @@ docs/tasks/
канонический**. `--roadmap-sections` у `init` нет: выбирать нечего.
**Заголовок секции отбит пустой строкой с обеих сторон и написан с прописной.**
Во всех индексах одинаково, включая секции беклога, которые проект называет сам.
Во всех индексах одинаково, включая категории беклога, которые проект называет сам.
Написание канонических секций правит `check --fix` (заодно и ссылку на секцию в
мете файлов: имя секции принадлежит заголовку индекса, файл на неё только
ссылается); отбивку и порядок он правит везде.
@@ -143,10 +155,10 @@ stateDiagram-v2
state "записи нет — реализована" as D
state "ROADMAP.md, «умеет» — цель достигнута" as A
[*] --> B: add
[*] --> B: add --type feature|fix|chore|research
[*] --> P: add --type goal
B --> P: edit --type goal --section
P --> B: edit --type task --section
P --> B: edit --type feature|fix|chore|research --section
B --> S: sprint take
S --> B: sprint drop --reason
S --> D: close --implemented
@@ -169,7 +181,7 @@ stateDiagram-v2
## Цели
**Цель — возможность приложения.** Такой же файл в `items/`, тип `[goal]`,
**Цель — возможность приложения.** Такой же файл в `items/`, тип `goal` (🎯),
перечисленный в `ROADMAP.md`. Формулируется ответом на вопрос **«что приложение
будет уметь»**, а не названием области работ: не «Работа с чтением», а «Чтение
данных клиентами»; не «Рефакторинг слияния», а «Исход слияния не зависит от
@@ -226,52 +238,51 @@ stateDiagram-v2
проектов. Встретился в чужом беклоге — это цель либо набор задач, и `check`
назовёт его неизвестным типом.
## Род работы
## Тип записи
**Тип записи и род работы — две оси, и путать их нельзя.** Тип отвечает «что это
за запись» (цель, идея, задача), род — «какого рода работа»: `feature`, `fix`,
`chore`, `research`. Одним значением на оба вопроса не ответить: идея бывает
*про* функцию, а цель функцией *и является*.
**Тип — единственная ось, и он решает, что с записью можно делать.** Дом типа —
**поле меты `Тип` первой строкой**; эмодзи в заголовке H1 от него производна, её
ставит `add` и чинит `check --fix`.
- **`feature`** — снаружи появляется или меняется то, чего раньше не было.
- **`fix`** — поведение расходится с заявленным, и расхождение воспроизводится.
Не воспроизводится — это `research`, а не `fix`.
- **`chore`** — обслуживание: зависимости, сборка, перенос, чистка. Наблюдаемое
поведение не меняется, и в этом всё дело: **у `chore` тест готовности слабее
честно**, а не молча. «Что станет наблюдаемо иначе» здесь отвечается
разработчику («перестанет собираться два раза», «уедет последний вызов
устаревшего API»), а не пользователю. Пока рода не было, такие задачи либо не
заводились, либо формулировались как выдуманная польза.
- **`research`** — исход работы знание, а не изменение системы: ответ на вопрос,
замер, разведка. Приёмка — записанный ответ (`docs/research/`, ADR, тело
задачи), а не изменённый код.
| Тип | Обязательные разделы | Цель | В спринт | Устав |
| --- | --- | --- | --- | --- |
| 🎯 `goal` | `Завершение` | — | нет | [task-goal.md](references/task-goal.md) |
| ✨ `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) |
Дом рода — **тег `kind:<род>`**, а не префикс заголовка и не поле меты: теги
здесь единственный механизм разметки, и `list --kind fix` работает даром. Цена
известна: в строку индекса род не попадает (индексы производны), и «в наборе одни
починки» видно командой, а не глазами по `SPRINT.md`.
Сверх обязательных у любой задачи допустимы `Рамки` и `Вопросы`. Раздел не из
схемы своего типа — **замечание, а не ошибка**: свой раздел законная вольность
проекта, но `Воспроизведение` у `chore` почти всегда значит, что тип проставлен
не тот, и сказать об этом стоит, не запрещая.
**Осей было две, и ортогональность у них была фальшивой.** Тип записи
(`goal`/`idea`/`task`) и род работы (`kind:<род>` тегом) давали двенадцать клеток
произведения, из которых законны были шесть: у цели род запрещён, у задачи
обязателен, у идеи пуст. Плюс алгоритм работы крепится не к `task`, а к `fix` и
`research` — то есть к роду. Оси схлопнуты, тег `kind:` упразднён.
**Тип `idea` упразднён вместе с ними.** Он значил не род работы, а **состояние
незаполненности** — «первый, второй или третий вопрос теста готовности не
отвечается», — а состояние типом быть не может: оно меняется по мере того, как
запись дописывают, а тип меняют командой. Теперь это состояние называется честно:
`research` без раздела «Вопрос» — **сырьё**. В спринт не берётся ровно как
прежняя идея, лежит в конце своей категории и отбирается `list --raw`.
Словарь **закрыт**. Открытый разъедется на синонимах — `bug`, `bugfix`, `fix`,
`defect`, — и отбор по роду перестанет отвечать на свой единственный вопрос. Ни
один род не подходит — это сигнал, что в задаче их два и её надо разделить.
`defect`, — и отбор по типу перестанет отвечать на свой единственный вопрос. Ни
один тип не подходит — это сигнал, что в задаче их два и её надо разделить.
**Род обязателен у задачи, у цели запрещён, у идеи необязателен** — идея получает
его, когда становится задачей. Требуется он там, где по нему принимают решение:
`sprint take` без рода откажет. `check` о пропаже только **напоминает** — беклог,
заведённый до появления рода, законен, и переоформлять его «заодно» здесь не
просят.
**Требуется тип там, где по нему принимают решение:** `sprint take` без типа
откажет, потому что не знает, каких разделов требовать. `check` о пропаже только
**напоминает** — беклог, заведённый до появления типа, законен, и переоформлять
его «заодно» здесь не просят.
**Род решает и то, обязательна ли цель.** `feature` без цели не бывает: новая
возможность и есть содержание цели, и если подходящей нет — либо она заводится,
либо это не `feature`. `fix`, `chore` и `research` живут без цели законно, и
`check` о них молчит: они служат работоспособности, а не направлению. Это
единственный случай, когда род что-то определяет за пределами отбора, — и
определяет он учёт, а не процесс проверки.
**Род не выбирает профиль ревью и вообще ничего не предписывает пайплайну.**
Профиль выбирается по факту изменения, а не по роду задачи: `chore` бывает
**Тип не выбирает профиль ревью и вообще ничего не предписывает пайплайну.**
Профиль выбирается по факту изменения, а не по типу задачи: `chore` бывает
миграцией схемы, `fix` — правкой публичного контракта. Правило «предписание
процесса в теле задачи снимается» родом не отменяется, а подтверждается: он
процесса в теле задачи снимается» типом не отменяется, а подтверждается: он
описывает работу, а не то, как её проверять.
## Как написана задача
@@ -283,17 +294,18 @@ stateDiagram-v2
| Тип | Отвечает на | Пример |
| --- | --- | --- |
| цель | что приложение будет уметь | Соперником может быть компьютер |
| задача | что нужно сделать | Печатать поле одним куском кода |
| идея | о чём она | Подсказка следующего хода |
| 🎯 `goal` | что приложение будет уметь | Соперником может быть компьютер |
| `feature`, 🐞 `fix`, 🧹 `chore` | что нужно сделать | Печатать поле одним куском кода |
| 🔬 `research` | о чём разведка | Подсказка следующего хода |
Задача — **глаголом в неопределённой форме**, перед ним допускается «не»: «Не
отбрасывать молча лишние символы в ходе», а не «Лишние символы молча
отбрасываются». Описательный заголовок называет **состояние**, а из состояния не
видно, чего от работы ждут: «Ничья объявляется, пока клетки есть» одинаково
читается и как жалоба, и как задание, — и в списке, где решают «брать или не
брать», это разные вещи. Идея формы действия не несёт **намеренно**: что делать,
ещё неизвестно, и заголовок-действие обещал бы решённость, которой нет.
брать», это разные вещи. `research` формы действия не несёт **намеренно**: её
исход знание, что делать — ещё неизвестно, и заголовок-действие обещал бы
решённость, которой нет.
Из этого же правила растёт разница индексов: роадмап — список возможностей,
беклог — список работ, и если заголовки перепутать формами, каждый из них
@@ -336,7 +348,7 @@ stateDiagram-v2
И одно требование, которое есть только у задачи: **сложность формулировки — не
признак сложности работы.** Задачу, которую не удаётся сказать просто, чаще
всего не удаётся и оценить: это либо две задачи, либо идея.
всего не удаётся и оценить: это либо две задачи, либо сырьё.
Эти правила — про **язык**, а не про объём: короткая задача без границ хуже
длинной с ними.
@@ -349,10 +361,10 @@ stateDiagram-v2
```
python3 $tk check --dir D # согласованность индексов + здоровье
python3 $tk check --dir D --fix # + починить дрейф (секция, заголовок, дубли, «зачем», форма меты)
python3 $tk list --dir D [--stale] [--section S] [--type T] [--kind K] [--tag a,b] [--goal S] [--index …] [--questions]
python3 $tk add --dir D --slug S --title T [--type goal|idea] [--section S] [--goal G] [--kind K] [--why «зачем»] [--tag a,b]
python3 $tk edit S --dir D [--title T] [--why «зачем»] [--type T] [--goal G] [--kind K] [--add-tag a,b] [--rm-tag c]
python3 $tk check --dir D --fix # + починить дрейф (тип, эмодзи, место, заголовок, дубли, «зачем», форма меты)
python3 $tk list --dir D [--stale] [--section S] [--type T] [--tag a,b] [--goal S] [--raw] [--index …] [--questions]
python3 $tk add --dir D --slug S --title T --type goal|feature|fix|chore|research [--section S] [--goal G] [--why «зачем»] [--tag a,b]
python3 $tk edit S --dir D [--title T] [--why «зачем»] [--type T] [--goal G] [--add-tag a,b] [--rm-tag c]
python3 $tk move S --dir D --section S [--reason R] [--after S | --first]
python3 $tk close S --dir D --reason R # в REJECTED.md + удалить (ушла без реализации)
python3 $tk close S --dir D --implemented # просто удалить (реализована и закоммичена)
@@ -375,20 +387,22 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
Различать 1 и 3 обязательно: «дрейф в беклоге» — рабочая ситуация, «каталога
нет» — нерабочая, и одинаковая реакция на них была бы неверна в обоих случаях.
Тип — английское ключевое слово `goal` / `idea` / `task` (как и прочие токены
команд); `task` префикса не несёт, остальные кодируются `[goal]`/`[idea]` в
заголовке. Текст задачи при этом русский.
Тип — английское ключевое слово `goal` / `feature` / `fix` / `chore` /
`research` (как и прочие токены команд), у `add` **обязательное**: без него
неизвестно, какой шаблон тела класть. Текст задачи при этом русский, а эмодзи в
заголовке ставит скрипт.
**Мутации правят файл и индексы заодно** — руками строку индекса или мету
не пиши, зови `add`/`edit`/`move`/`close`/`sprint`. Смена заголовка, «зачем», типа,
цели, рода работы и **тегов** — это `edit`: он держит H1, мету и индекс в синхроне.
Снятие тега — `--rm-tag` (после ответа на вопрос снимается `question`), смена
цели — `--goal`, рода`--kind`; оба заменяют прежнее значение, а не добавляют
второе.
цели и **тегов** — это `edit`: он держит H1 (вместе с эмодзи), мету и индекс в
синхроне. Снятие тега — `--rm-tag` (после ответа на вопрос снимается
`question`), смена цели — `--goal`, типа`--type`; оба заменяют прежнее
значение, а не добавляют второе.
**Переезд между индексами — следствие смены типа, а не отдельная команда.**
`edit <slug> --type goal --section <часть роадмапа>` переносит строку из
`BACKLOG.md` в `ROADMAP.md` (и обратно `--type task --section <секция беклога>`);
`BACKLOG.md` в `ROADMAP.md` (и обратно — задачным типом плюс
`--section <категория беклога>`);
`move` двигает только внутри одного индекса и пишет причину. `--section` у
`edit` работает **только** при таком переезде — иначе он отсылает к `move`,
потому что смена секции без причины и есть тот дрейф, который потом никто не
@@ -401,39 +415,54 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
`check` — единственный судья согласованности; что именно он ловит, скажет его
вывод, здесь не пересказываем. Гоняй его **в начале сессии** и **после каждой
правки**, даже если правил мутациями: дрейф мог накопиться раньше. Накопившееся
чини `check --fix` — он детерминированно правит то, где истина однозначна
(секция, заголовок, дубли, «зачем» из индекса в файл, старая форма меты,
пометка `decomposed` у цели с задачами), а неоднозначное (задача сразу в двух
индексах, нечего восстанавливать) печатает отдельной пометкой `НЕОДНОЗНАЧНО`
это тебе, и это идёт строкой доклада. **Ссылка на исчезнувший файл в пометку не
попадает:** `--fix` её просто не трогает, и она остаётся `ОШИБКА` обычного
`check` — то есть видна, но в докладе её надо назвать отдельно.
чини `check --fix` — он детерминированно правит то, где истина однозначна (тип в
своё поле, эмодзи заголовка, имя поля места, секция, заголовок, дубли, «зачем» из
индекса в файл, старая форма меты, пометка `decomposed` у цели с задачами, сырьё
в конец категории), а неоднозначное (задача сразу в двух индексах, нечего
восстанавливать, **тип, которого неоткуда взять**) печатает отдельной пометкой
`НЕОДНОЗНАЧНО` — это тебе, и это идёт строкой доклада. **Ссылка на исчезнувший
файл в пометку не попадает:** `--fix` её просто не трогает, и она остаётся
`ОШИБКА` обычного `check` — то есть видна, но в докладе её надо назвать отдельно.
`--fix` правит **и файлы**ровно в двух местах, где источник ровно один и
выбирать не из чего: «зачем», оставшееся только в индексе, переезжает в мету,
и цель, у которой есть задачи, получает тег `decomposed`. Оба случая печатаются
поимённо.
`--fix` правит **и файлы** — там, где источник ровно один и выбирать не из чего:
тип переезжает из прежнего дома (тег `kind:`, префикс `[goal]`/`[idea]`) в поле
меты, заголовок получает эмодзи, поле места — имя по типу, «зачем», оставшееся
только в индексе, переезжает в мету, цель с задачами получает `decomposed`.
Каждый случай печатается поимённо.
**Тип, который не выводится ниоткуда, `--fix` не угадывает.** `feature` от
`chore` машина не отличает, и подставленное наугад значение врало бы ровно там,
где по нему принимают решение. Такие записи идут в `НЕОДНОЗНАЧНО`, и тип им
проставляет человек — `edit <слаг> --type …`.
**Что механизировано, а что нет.** У задачи, взятой в набор (`sprint take` и
`check` по задачам спринта), проверяются три вещи, и у каждой своя глубина:
`check` по задачам спринта), проверяется схема её типа, и у каждой части своя
глубина:
- **критерии приёмки** — число пунктов жёстко (меньше двух отказ, больше пяти
замечание), наличие оракула **эвристикой** по слову «оракул» в пункте;
- **род работы** — жёстко: назван и из закрытого словаря;
- **раздел «Затрагивает»** — только **наличие непустого**. Полнота перечня машине
не видна: границу, которую забыли назвать, она от отсутствующей не отличает.
- **тип** — жёстко: назван и из закрытого словаря;
- **критерии приёмки** (`feature`, `fix`, `chore`) — число пунктов жёстко
(меньше двух отказ, больше пяти замечание), наличие оракула **эвристикой** по
слову «оракул» в пункте;
- **прочие разделы схемы** (`Затрагивает`, `Воспроизведение`, `Вопрос`,
`Куда ляжет ответ`, `Завершение`) — только **наличие непустого**. Содержимое
машине не видно: границу, которую забыли назвать, она от отсутствующей не
отличает, а шаги, по которым ничего не воспроизводится, — от годных.
Настоящий оракул от слова «оракул» машина тоже не отличает, поэтому эвристика
даёт только замечание, и в докладе это называется как есть: «проверено число
пунктов и наличие границ, годность оракулов и полнота границ — глазами».
даёт только замечание, и в докладе это называется как есть: «проверено наличие
разделов своего типа и число критериев, годность оракулов и полнота границ —
глазами».
Формат файла, меты, слага, индексов и `REJECTED.md`
[references/task-format.md](references/task-format.md). Там же тест «готова к
взятию», требования к критериям приёмки и раздел «Затрагивает».
Формат записи, меты, слага, индексов и `REJECTED.md`
[references/task-format.md](references/task-format.md); там же тест «готова к
взятию». Схема и алгоритм каждого типа — по файлу на тип:
[goal](references/task-goal.md) · [feature](references/task-feature.md) ·
[fix](references/task-fix.md) · [chore](references/task-chore.md) ·
[research](references/task-research.md).
## Сценарии
### Завести задачу, идею или цель из диалога
### Завести запись из диалога
1. **Фильтр.** Делаем прямо сейчас — не заводим. Не пожалеем о потере — не
заводим. Родилось три кандидата — покажи их и спроси, какие заводить: молча
@@ -444,30 +473,36 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
ту строку и что изменилось с момента отказа (`add` предупредит и сам, но
молча заводить нельзя). Две задачи об одном — самая дорогая находка
переоценки.
3. **Тип по тесту готовности** (см. task-format): проходит — задача, не
проходит — идея (`--type idea`). Не делается одним заходом — это не эпик, а
несколько задач под одной целью: дроби сразу. Возможность приложения, а не
шаг — цель (`--type goal`).
4. **Цель задачи — если род её требует.** У `feature` должен быть
`--goal <слаг>`: новая возможность и есть содержание цели. Подходящей нет —
либо она заводится (`--type goal`), либо перед тобой не `feature`. У `fix`,
`chore` и `research` цели может не быть вовсе, и придумывать её не надо. У
идеи цель проставляется, когда идея становится задачей.
5. **Род работы**`--kind feature|fix|chore|research` (см. «Род работы»). Не
подходит ни один — задача не одна, разбирай.
6. `add …`, затем допиши тело редактором: одна фраза, **затрагиваемые границы**,
критерии приёмки с оракулами, рамки. «Зачем» отвечает «зачем нужна эта
задача» — состояние, остаток, боль, — а не пересказывает первый абзац, и
пишется **для человека**: не «канонизация внутри транзакции», а «тело 40 МиБ
держит блокировку 5 секунд, соседние доставки уходят в отказ».
7. `check`.
3. **Тип**`--type` обязателен, и он же первое содержательное решение:
- возможность приложения, а не шаг к ней → `goal`;
- снаружи появляется то, чего не было → `feature`;
- поведение расходится с заявленным и **воспроизводится** `fix`
(не воспроизводится → `research`);
- обслуживание, наблюдаемое поведение не меняется → `chore`;
- исход — знание, а не изменение системы → `research`.
Не подходит ни один — в записи их два, разбирай. Не проходит тест готовности
(см. task-format) — это **сырьё**: `--type research`, раздел «Вопрос» пока
пуст, место в конце категории. Не делается одним заходом — это не эпик, а
несколько задач под одной целью: дроби сразу.
4. **Цель — если тип её требует.** У `feature` должен быть `--goal <слаг>`:
новая возможность и есть содержание цели. Подходящей нет — либо она
заводится (`--type goal`), либо перед тобой не `feature`. У `fix`, `chore` и
`research` цели может не быть вовсе, и придумывать её не надо.
5. `add …`, затем допиши тело редактором **по схеме своего типа** — шаблон её
уже разложил, устав типа объясняет каждый раздел. «Зачем» отвечает «зачем
нужна эта задача» — состояние, остаток, боль, — а не пересказывает первый
абзац, и пишется **для человека**: не «канонизация внутри транзакции», а
«тело 40 МиБ держит блокировку 5 секунд, соседние доставки уходят в отказ».
6. `check`.
### Разобрать находки аудита или ревью
Ревью и аудиты — тоже источник задач, но с зеркальной диалогу опасностью: не
пять файлов из одной мысли, а сорок файлов из сорока сырых находок. Защита та
же, что в самом ревью: кластеризация по причине, дедуп против живых и
`REJECTED.md`, находка без свидетельства → идея, а не задача, и карта кластеров
`REJECTED.md`, находка без свидетельства → сырьё (`research`), а не задача, и карта кластеров
пользователю до создания файлов. Порядок, отображение серьёзности и привязка к
целям — [references/from-review.md](references/from-review.md).
@@ -481,7 +516,7 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
Если переводить надо не только задачи, а весь `docs/` — это скилл
`av-dev-pm:canon`, и он зовёт этот сценарий сам на своём шаге.
### Декомпозиция и штурм идеи
### Декомпозиция и штурм сырья
[references/split.md](references/split.md). Обе операции превращают одну запись в
несколько, и у обеих есть проверяемый тест: части должны **мерджиться порознь** и
@@ -551,10 +586,14 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
- **предписание процесса в теле** — «делать таким-то профилем ревью», «взять
такой-то агент»: это второй дом для правила выбора и путь понизить требования
решением, принятым до проектирования. Снимается;
- **род, разошедшийся с задачей** — задача заводилась починкой, а после разбора
- **тип, разошедшийся с задачей** — задача заводилась починкой, а после разбора
оказалось, что поведение никогда и не было заявлено: это `feature`, а не `fix`.
Правится `edit <slug> --kind`; род, оставшийся от прошлой формулировки, врёт
ровно там, где по нему отбирают;
Правится `edit <slug> --type`; тип, оставшийся от прошлой формулировки, врёт
ровно там, где по нему отбирают, **и требует не тех разделов**: у брошенного
`fix` останется «Воспроизведение», которого нечем заполнить;
- **сырьё, у которого появился вопрос** — разведка обросла формулировкой, но
раздел «Вопрос» так и пуст: она числится сырьём и в спринт не берётся.
Записывается вопрос, и `check --fix` поднимает строку из конца категории;
- **границы, названные вместо реализации** — «переписать хранилище на новый
драйвер» в разделе «Затрагивает» это не граница, а замысел. Границы —
`таблица points и её миграция`, `эндпоинт POST /ingest`, `формат отпечатка на
@@ -619,7 +658,7 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
- **Развилки — пользователю.** Через `AskUserQuestion`, с уже сформулированным
предварительным суждением (**рекомендация — первым вариантом**). Что выкинуть,
под какую цель отнести, какая рамка идеи верна — решение пользователя. Слаг,
под какую цель отнести, какая рамка разведки верна — решение пользователя. Слаг,
формулировка, порядок строк в индексе — механика, делаем сами.
- **Не больше трёх вопросов за раз.** Пачка длиннее трёх тяжела для ответа;
решений больше — веди **несколько итераций** диалога по ≤3, а не один