скилл tasks: приоритет стал порядком строк в беклоге

Правило 4 переписано целиком. Было «порядка нет, есть цель», и
обосновано это было тем, что на «что делать дальше» отвечает набор
спринта. Набора нет — вопрос остался, отвечать нечем.

Приоритет — свойство очереди, а не задачи, поэтому его дом индекс: то
же исключение из правила 2, что и «в каком индексе лежит запись».
Положи его в файл числом — два соседних файла смогли бы утверждать одно
место, а строка индекса противоречить обоим. Цель и приоритет —
независимые оси: очередь может идти поперёк целей.

Расстановка — это move --after и move --first, и только они: руками
поправленная строка не оставляет причины.

Место сырья в конце секции из очереди изъято: оно производно от типа и
заполненности, его назначает машина, приоритетом оно не становится.

Схема состояний потеряла SPRINT.md и четыре перехода; шесть уставов
типов, task-format, split, from-review и adopt переведены со «взятия в
спринт» на ready.
This commit is contained in:
av
2026-08-09 16:36:26 +03:00
parent a73eedb893
commit 3653c5cff5
11 changed files with 142 additions and 138 deletions
+70 -50
View File
@@ -1,6 +1,6 @@
--- ---
name: tasks name: tasks
description: Ведение задач и целей как каталога markdown-файлов (одна запись = один файл в items/ + строка в одном из индексов). У каждой записи есть тип (goal, feature, fix, chore, research), и тип решает, каких разделов она требует и что с ней можно делать. Заведение записи из диалога, разбор находок аудита/ревью, декомпозиция на независимо полезные части, штурм сырья, гигиена полей и проверка согласованности индексов. Использовать, когда просят добавить задачу/идею/цель, превратить находки ревью в задачи, разбить задачу, проработать идею, поправить формат или проверить беклог. Ритуал между спринтами — скилл session. Не реализует задачи — этим занимается пайплайн проекта. description: Ведение задач и целей как каталога markdown-файлов (одна запись = один файл в items/ + строка в одном из индексов). У каждой записи есть тип (goal, feature, fix, chore, research), и тип решает, каких разделов она требует и что с ней можно делать. Заведение записи из диалога, разбор находок аудита/ревью, декомпозиция на независимо полезные части, штурм сырья, гигиена полей и проверка согласованности индексов. Использовать, когда просят добавить задачу/идею/цель, превратить находки ревью в задачи, разбить задачу, проработать идею, поправить формат или проверить беклог. Расстановка приоритетов и разбор накопившегося — скилл groom. Не реализует задачи — этим занимается скилл решения задачи.
--- ---
# Задачи # Задачи
@@ -9,9 +9,9 @@ description: Ведение задач и целей как каталога mar
строка **ровно в одном** индексе. Скилл владеет **форматом и содержимым**: строка **ровно в одном** индексе. Скилл владеет **форматом и содержимым**:
заводит, редактирует, закрывает, разбирает находки ревью, дробит, штурмует сырьё. заводит, редактирует, закрывает, разбирает находки ревью, дробит, штурмует сырьё.
Чем он **не** владеет: ритуалом между спринтами (разбор вопросов → разбор Чем он **не** владеет: **очередью** — что делать следующим и что перестало быть
прошедшего спринта → переоценка → выбор цели и набор) — это скилл `session`; и важным, решает скилл `groom`, а этот скилл лишь даёт ему операции; и выполнением
выполнением задачи — это пайплайн проекта. задачи — это пайплайн проекта.
## Шесть правил, из которых всё следует ## Шесть правил, из которых всё следует
@@ -35,27 +35,38 @@ description: Ведение задач и целей как каталога mar
Поэтому **«зачем» живёт в мете файла**, а строка индекса его лишь Поэтому **«зачем» живёт в мете файла**, а строка индекса его лишь
повторяет: пока поле лежало только в индексе, восстановление пропавшей повторяет: пока поле лежало только в индексе, восстановление пропавшей
строки теряло его молча и навсегда. Единственное исключение намеренное: **в каком строки теряло его молча и навсегда. Единственное исключение намеренное: **в каком
индексе лежит задача, знают индексы** — «в спринте» это свойство спринта, а индексе лежит запись, знают индексы** — поля-состояния в файле нет. И
не файла, поля-состояния нет. **порядок строк в беклоге**: приоритет это свойство очереди, а не задачи, и в
файле ему места нет (правило 4).
3. **Причина переживает запись.** Выкинутая без причины задача вернётся через 3. **Причина переживает запись.** Выкинутая без причины задача вернётся через
квартал тем же текстом. Реализованная оставляет след в коммите — выкинутая не квартал тем же текстом. Реализованная оставляет след в коммите — выкинутая не
оставляет ничего, поэтому у неё есть `REJECTED.md`. оставляет ничего, поэтому у неё есть `REJECTED.md`.
4. **Порядка нет, есть цель — но цель есть не у всякой задачи.** Приоритетов, 4. **Приоритет — это порядок строк, а цель есть не у всякой задачи.** Очередь
«повысить» и «встать раньше» нет: «что делать дальше» отвечает набор спринта, внутри секции беклога значима: **первая строка — то, что делают следующим**.
а между спринтами порядок не нужен никому. Цель обязательна там, где она и Приоритет назначает человек на груминге, машина его не выводит и не угадывает.
есть содержание работы, — у **новой возможности** (`feature`). Починка,
техдолг и разведка служат работоспособности, а не направлению, и живут без
цели законно; в набор спринта они входят помимо его цели. Придуманная им цель
— то же враньё, от которого спасает тип.
Единственный порядок, который в беклоге всё-таки есть, **производен от типа**, Прежде здесь стояло «порядка нет, есть цель», и обосновано это было тем, что
а не назначен человеком: **сырьё** (`research` без раздела «Вопрос») стоит в на «что делать дальше» отвечает **набор спринта**. Набора больше нет, а
конце своей категории. Его не берут, и между берущимся оно каждый раз требует вопрос остался — и без порядка отвечать на него стало нечем.
открыть файл, чтобы это понять. Раз порядок выводится, его проверяет машина —
и приоритетом он не становится. **Дом приоритета — индекс, а не файл.** Это то же исключение из правила 2,
что и «в каком индексе лежит запись»: приоритет — свойство очереди. Положи он
в файл числом, и два соседних файла смогли бы утверждать одно и то же место,
а строка индекса — противоречить обоим.
Цель обязательна там, где она и есть содержание работы, — у **новой
возможности** (`feature`). Починка, техдолг и разведка служат
работоспособности, а не направлению, и живут без цели законно. Придуманная им
цель — то же враньё, от которого спасает тип. **Цель и приоритет —
независимые оси:** очередь может идти поперёк целей, и это законно.
Одно место в очереди назначено **не человеком, а типом**: **сырьё**
(`research` без раздела «Вопрос») стоит в конце своей категории. Его не берут,
и между берущимся оно каждый раз требует открыть файл, чтобы это понять. Раз
это выводится, проверяет и чинит это машина.
5. **Тип решает, что с записью можно делать.** Тип — единственная ось и первое 5. **Тип решает, что с записью можно делать.** Тип — единственная ось и первое
поле меты: от него зависит, какие разделы обязательны в теле, нужна ли цель, поле меты: от него зависит, какие разделы обязательны в теле, нужна ли цель,
берётся ли запись в спринт и в каком индексе живёт её строка. Словарь закрыт; берётся ли запись в работу и в каком индексе живёт её строка. Словарь закрыт;
ни один тип не подошёл — значит, в записи их два, и её надо разделить. ни один тип не подошёл — значит, в записи их два, и её надо разделить.
## Раскладка ## Раскладка
@@ -70,14 +81,14 @@ description: Ведение задач и целей как каталога mar
tasks/ tasks/
items/ задачи и цели файлами, <slug>.md, слаги английские items/ задачи и цели файлами, <slug>.md, слаги английские
ROADMAP.md состояние проекта: что уже умеет и чего ещё не умеет ROADMAP.md состояние проекта: что уже умеет и чего ещё не умеет
BACKLOG.md что можно взять — только задачи, целей здесь нет BACKLOG.md что можно взять — только задачи, целей здесь нет.
SPRINT.md текущий спринт: цель (или её отсутствие), набор, дата Порядок строк в секции значим: это очередь
REJECTED.md ушедшее БЕЗ реализации, с причиной и датой REJECTED.md ушедшее БЕЗ реализации, с причиной и датой
``` ```
Правило, снимающее путаницу: **`BACKLOG.md` — то, что берут; `ROADMAP.md` — то, Правило, снимающее путаницу: **`BACKLOG.md` — то, что берут; `ROADMAP.md` — то,
подо что берут.** Цель в спринт взять нельзя, поэтому в списке берущихся ей не подо что берут.** Цель в работу взять нельзя — берут её задачи, — поэтому в
место. списке берущихся ей не место.
**Четыре секции роадмапа, и последняя отвечает на половину вопроса:** **Четыре секции роадмапа, и последняя отвечает на половину вопроса:**
@@ -99,7 +110,7 @@ tasks/
роадмап, названный по-своему, читался бы только своим автором. Категории беклога роадмап, названный по-своему, читался бы только своим автором. Категории беклога
(`Ядро`, `Инфра`) смысла не несут — это полки домена, и остаются делом проекта. (`Ядро`, `Инфра`) смысла не несут — это полки домена, и остаются делом проекта.
Отсюда и разные имена поля меты: у цели **Секция** (часть роадмапа — состояние Отсюда и разные имена поля меты: у цели **Секция** (часть роадмапа — состояние
очереди), у задачи **Категория** (полка, в которую она вернётся из спринта). очереди), у задачи **Категория** (полка домена, на которой она лежит).
Отсюда четыре правила, которые проверяет `tasks.py check`: **состав закреплён** Отсюда четыре правила, которые проверяет `tasks.py check`: **состав закреплён**
(чужая секция — ошибка, а не вольность), **все четыре обязаны быть** (нет (чужая секция — ошибка, а не вольность), **все четыре обязаны быть** (нет
@@ -118,24 +129,31 @@ tasks/
называла слишком много: роадмап **весь** про разработку, и секция с таким именем называла слишком много: роадмап **весь** про разработку, и секция с таким именем
не отличалась от остальных ничем. не отличалась от остальных ничем.
**Секции «блокеры» в беклоге нет.** Блокер — это *состояние* (спринт не может **Секции «блокеры» в беклоге нет.** Блокер — это *состояние* (работа не может
продолжаться ни одной задачей), а не полка: он живёт ровно до ответа человека, и продолжаться ни одной задачей), а не полка: он живёт ровно до ответа человека, и
записи в такой секции не успевают жить. Следы блокера остаются вопросами в записи в такой секции не успевают жить. Следы блокера остаются вопросами в
файлах задач распущенного спринта. Постоянно пустая секция со старой семантикой файлах задач. Постоянно пустая секция со старой семантикой
«разбираются пачками» противоречила бы правилу «блокер эскалируется немедленно», «разбираются пачками» противоречила бы правилу «блокер эскалируется немедленно»,
поэтому `init` её заводить отказывается, а `check` о ней говорит. **Проекту, поэтому `init` её заводить отказывается, а `check` о ней говорит. **Проекту,
который переезжает с такой секцией, её надо удалить** — это единственное место, который переезжает с такой секцией, её надо удалить** — это единственное место,
где это сказано. где это сказано.
**Задача живёт в одном индексе за раз.** Взята в спринт — строка переезжает из **Запись живёт в одном индексе за раз.** Индексов два, и выбирает между ними
`BACKLOG.md` в `SPRINT.md`; вышла — обратно. Файл в `items/` при этом **не тип: цель в роадмапе, задача в беклоге. Сменился тип — строка переезжает
двигается**: он и есть запись, индексы лишь показывают, где она числится. (`edit --type`). Файл в `items/` при этом **не двигается**: он и есть запись,
индексы лишь показывают, где она числится и в каком порядке стоит.
**Порядок строк в беклоге — приоритет**, и он единственное, чего в файле нет
(правило 4). Отсюда следствие для всякой машинной правки индекса:
восстановленная или перенесённая строка встаёт **в конец своей секции**, и
скрипт об этом говорит. Молчаливая вставка выдала бы машинную позицию за
решение человека — а решение это его.
**У сделанной задачи записи не остаётся** — файл и строка удаляются (`close **У сделанной задачи записи не остаётся** — файл и строка удаляются (`close
--implemented`). Ей хватает коммита и документации проекта; вторая запись была --implemented`). Ей хватает коммита и документации проекта; вторая запись была
бы вторым домом для того же факта. Вопрос «что было в спринте N» отвечается бы вторым домом для того же факта. Вопрос «что было сделано и когда» отвечается
даром: `SPRINT.md` лежит под git, `git log -p tasks/SPRINT.md` отдаёт историю даром: индексы лежат под git, а закрытие коммитится отдельным коммитом учёта —
всех наборов без отдельного журнала. `git log -p tasks/BACKLOG.md` отдаёт историю без отдельного журнала.
**У достигнутой цели запись остаётся, и это единственное исключение.** Файл **У достигнутой цели запись остаётся, и это единственное исключение.** Файл
удаляется так же, а строка переезжает в секцию `Готово` с датой. Причина в том, удаляется так же, а строка переезжает в секцию `Готово` с датой. Причина в том,
@@ -152,7 +170,6 @@ tasks/
stateDiagram-v2 stateDiagram-v2
state "BACKLOG.md — что берут" as B state "BACKLOG.md — что берут" as B
state "ROADMAP.md — подо что берут" as P state "ROADMAP.md — подо что берут" as P
state "SPRINT.md — набор спринта" as S
state "REJECTED.md — ушла без реализации" as R state "REJECTED.md — ушла без реализации" as R
state "записи нет — реализована" as D state "записи нет — реализована" as D
state "ROADMAP.md, «умеет» — цель достигнута" as A state "ROADMAP.md, «умеет» — цель достигнута" as A
@@ -161,12 +178,9 @@ stateDiagram-v2
[*] --> P: add --type goal [*] --> P: add --type goal
B --> P: edit --type goal --section B --> P: edit --type goal --section
P --> B: edit --type feature|fix|chore|research --section P --> B: edit --type feature|fix|chore|research --section
B --> S: sprint take B --> D: close --implemented
S --> B: sprint drop --reason
S --> D: close --implemented
P --> A: close --implemented P --> A: close --implemented
B --> R: close --reason B --> R: close --reason
S --> R: close --reason
P --> R: close --reason P --> R: close --reason
D --> B: reopen --reason D --> B: reopen --reason
R --> B: reopen --reason R --> B: reopen --reason
@@ -247,7 +261,7 @@ stateDiagram-v2
**поле меты `Тип` первой строкой**; эмодзи в заголовке H1 от него производна, её **поле меты `Тип` первой строкой**; эмодзи в заголовке H1 от него производна, её
ставит `add` и чинит `check --fix`. ставит `add` и чинит `check --fix`.
| Тип | Обязательные разделы | Цель | В спринт | Устав | | Тип | Обязательные разделы | Цель | В работу | Устав |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| 🎯 `goal` | `Завершение` | — | нет | [task-goal.md](references/task-goal.md) | | 🎯 `goal` | `Завершение` | — | нет | [task-goal.md](references/task-goal.md) |
| ✨ `feature` | `Затрагивает`, `Критерии приёмки` | **обязательна** | да | [task-feature.md](references/task-feature.md) | | ✨ `feature` | `Затрагивает`, `Критерии приёмки` | **обязательна** | да | [task-feature.md](references/task-feature.md) |
@@ -270,14 +284,14 @@ stateDiagram-v2
незаполненности** — «первый, второй или третий вопрос теста готовности не незаполненности** — «первый, второй или третий вопрос теста готовности не
отвечается», — а состояние типом быть не может: оно меняется по мере того, как отвечается», — а состояние типом быть не может: оно меняется по мере того, как
запись дописывают, а тип меняют командой. Теперь это состояние называется честно: запись дописывают, а тип меняют командой. Теперь это состояние называется честно:
`research` без раздела «Вопрос» — **сырьё**. В спринт не берётся ровно как `research` без раздела «Вопрос» — **сырьё**. В работу не берётся ровно как
прежняя идея, лежит в конце своей категории и отбирается `list --raw`. прежняя идея, лежит в конце своей категории и отбирается `list --raw`.
Словарь **закрыт**. Открытый разъедется на синонимах — `bug`, `bugfix`, `fix`, Словарь **закрыт**. Открытый разъедется на синонимах — `bug`, `bugfix`, `fix`,
`defect`, — и отбор по типу перестанет отвечать на свой единственный вопрос. Ни `defect`, — и отбор по типу перестанет отвечать на свой единственный вопрос. Ни
один тип не подходит — это сигнал, что в задаче их два и её надо разделить. один тип не подходит — это сигнал, что в задаче их два и её надо разделить.
**Требуется тип там, где по нему принимают решение:** `sprint take` без типа **Требуется тип там, где по нему принимают решение:** `ready` без типа
откажет, потому что не знает, каких разделов требовать. `check` о пропаже только откажет, потому что не знает, каких разделов требовать. `check` о пропаже только
**напоминает** — беклог, заведённый до появления типа, законен, и переоформлять **напоминает** — беклог, заведённый до появления типа, законен, и переоформлять
его «заодно» здесь не просят. его «заодно» здесь не просят.
@@ -324,7 +338,7 @@ stateDiagram-v2
делать, и какие границы это трогает: эндпоинт или команду, таблицу и миграцию, делать, и какие границы это трогает: эндпоинт или команду, таблицу и миграцию,
формат на диске, публичный тип пакета, внешний сервис. Перечень живёт разделом формат на диске, публичный тип пакета, внешний сервис. Перечень живёт разделом
«Затрагивает» (форма — [references/task-format.md](references/task-format.md)) и «Затрагивает» (форма — [references/task-format.md](references/task-format.md)) и
требуется к взятию в спринт. Без него задача оценивается по объёму текста, а не требуется к взятию в работу. Без него задача оценивается по объёму текста, а не
по объёму поверхности, — и оценка систематически занижена ровно там, где текст по объёму поверхности, — и оценка систематически занижена ровно там, где текст
короткий, а границ много. Названы **границы**, а не то, как они изменятся: план короткий, а границ много. Названы **границы**, а не то, как они изменятся: план
реализации живёт в предложении об изменении, а не в задаче. реализации живёт в предложении об изменении, а не в задаче.
@@ -373,7 +387,7 @@ 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 --reason R # в REJECTED.md + удалить (ушла без реализации)
python3 $tk close S --dir D --implemented # просто удалить (реализована и закоммичена) python3 $tk close S --dir D --implemented # просто удалить (реализована и закоммичена)
python3 $tk reopen S --dir D --reason R # вернуть закрытую: приёмка не сошлась python3 $tk reopen S --dir D --reason R # вернуть закрытую: приёмка не сошлась
python3 $tk sprint start (--goal S | --no-goal) --dir D | take S… | drop S… --reason R | close [--dissolve --reason R] python3 $tk ready S… --dir D # схема типа выполнена — можно брать в работу
python3 $tk init --dir D [--sections …] [--items …] [--backlog …] … python3 $tk init --dir D [--sections …] [--items …] [--backlog …] …
python3 $tk adopt scan --from … | apply --plan … # разовая адаптация, references/adopt.md python3 $tk adopt scan --from … | apply --plan … # разовая адаптация, references/adopt.md
``` ```
@@ -397,7 +411,7 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
заголовке ставит скрипт. заголовке ставит скрипт.
**Мутации правят файл и индексы заодно** — руками строку индекса или мету **Мутации правят файл и индексы заодно** — руками строку индекса или мету
не пиши, зови `add`/`edit`/`move`/`close`/`sprint`. Смена заголовка, «зачем», типа, не пиши, зови `add`/`edit`/`move`/`close`/`reopen`. Смена заголовка, «зачем», типа,
цели и **тегов** — это `edit`: он держит H1 (вместе с эмодзи), мету и индекс цели и **тегов** — это `edit`: он держит H1 (вместе с эмодзи), мету и индекс
согласованными. Снятие тега — `--rm-tag` (после ответа на вопрос снимается согласованными. Снятие тега — `--rm-tag` (после ответа на вопрос снимается
`question`), смена цели — `--goal`, типа — `--type`; оба заменяют прежнее `question`), смена цели — `--goal`, типа — `--type`; оба заменяют прежнее
@@ -410,7 +424,12 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
`move` двигает только внутри одного индекса и пишет причину. `--section` у `move` двигает только внутри одного индекса и пишет причину. `--section` у
`edit` работает **только** при таком переезде — иначе он отсылает к `move`, `edit` работает **только** при таком переезде — иначе он отсылает к `move`,
потому что смена секции без причины и есть тот дрейф, который потом никто не потому что смена секции без причины и есть тот дрейф, который потом никто не
объяснит. Задача в наборе спринта тип не меняет вовсе: сперва `sprint drop`. объяснит.
**`move --after <слаг>` и `move --first` — это и есть расстановка приоритета.**
Порядок строк в секции значим (правило 4), и двигают его только этой командой:
руками поправленная строка не оставляет причины, а причина здесь и есть половина
решения.
Тело задачи скрипт не трогает: Тело задачи скрипт не трогает:
`add` кладёт заголовок, мета-блок и шаблон с подсказками, тело дописываешь `add` кладёт заголовок, мета-блок и шаблон с подсказками, тело дописываешь
@@ -439,9 +458,9 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
где по нему принимают решение. Такие записи идут в `НЕОДНОЗНАЧНО`, и тип им где по нему принимают решение. Такие записи идут в `НЕОДНОЗНАЧНО`, и тип им
проставляет человек — `edit <слаг> --type …`. проставляет человек — `edit <слаг> --type …`.
**Что механизировано, а что нет.** У задачи, взятой в набор (`sprint take` и **Что механизировано, а что нет.** Схему типа проверяет `ready` на входе в
`check` по задачам спринта), проверяется схема её типа, и у каждой части своя работу — там, где по ней принимают решение; `check` о недостающем только
глубина: напоминает счётчиком «готово к взятию». У каждой части своя глубина:
- **тип** — жёстко: назван и из закрытого словаря; - **тип** — жёстко: назван и из закрытого словаря;
- **критерии приёмки** (`feature`, `fix`, `chore`) — число пунктов жёстко - **критерии приёмки** (`feature`, `fix`, `chore`) — число пунктов жёстко
@@ -602,7 +621,7 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
ровно там, где по нему отбирают, **и требует не тех разделов**: у брошенного ровно там, где по нему отбирают, **и требует не тех разделов**: у брошенного
`fix` останется «Воспроизведение», которого нечем заполнить; `fix` останется «Воспроизведение», которого нечем заполнить;
- **сырьё, у которого появился вопрос** — разведка обросла формулировкой, но - **сырьё, у которого появился вопрос** — разведка обросла формулировкой, но
раздел «Вопрос» так и пуст: она числится сырьём и в спринт не берётся. раздел «Вопрос» так и пуст: она числится сырьём и в работу не берётся.
Записывается вопрос, и `check --fix` поднимает строку из конца категории; Записывается вопрос, и `check --fix` поднимает строку из конца категории;
- **границы, названные вместо реализации** — «переписать хранилище на новый - **границы, названные вместо реализации** — «переписать хранилище на новый
драйвер» в разделе «Затрагивает» это не граница, а замысел. Границы — драйвер» в разделе «Затрагивает» это не граница, а замысел. Границы —
@@ -691,6 +710,7 @@ python3 $tk adopt scan --from … | apply --plan … # разовая адап
## Чего этот скилл не делает ## Чего этот скилл не делает
Не пишет код, не заводит спеки и предложения об изменении, не берёт задачу в Не пишет код, не заводит спеки и предложения об изменении, не берёт задачу в
работу — этим занимается пайплайн проекта. Не ведёт спринт и не проводит сессию работу — этим занимается пайплайн проекта. **Не ведёт очередь:** что делать
между спринтами — это `session`. Не решает за пользователя, что важно. Не следующим и что перестало быть важным — скилл `groom`, а этот даёт ему операции.
Не решает за пользователя, что важно. Не
переоформляет существующие задачи «заодно»: правится то, чего касается операция. переоформляет существующие задачи «заодно»: правится то, чего касается операция.
+10 -8
View File
@@ -2,7 +2,7 @@
Проект, где задачи уже как-то ведутся, и из имеющегося материала **выводится** Проект, где задачи уже как-то ведутся, и из имеющегося материала **выводится**
заполненный каталог задач: цели, задачи, кладбище, индексы. Операция разовая — заполненный каталог задач: цели, задачи, кладбище, индексы. Операция разовая —
после неё проект живёт скиллами `tasks` и `session`. после неё проект живёт скиллами `tasks` и `groom`.
**Это часть приведения проекта к канону.** Раскладку `docs/` целиком ведёт скилл **Это часть приведения проекта к канону.** Раскладку `docs/` целиком ведёт скилл
`av-dev-docs:canon`; он же зовёт этот сценарий на шаге «каталог задач», потому что `av-dev-docs:canon`; он же зовёт этот сценарий на шаге «каталог задач», потому что
@@ -94,13 +94,15 @@ python3 $tk adopt apply --plan tasks-adopt-plan.json \
быть названо, иначе следующий агент примет пустой беклог за поломку. быть названо, иначе следующий агент примет пустой беклог за поломку.
`apply` печатает состояние по факту: сколько задач без цели (это **ошибки** `apply` печатает состояние по факту: сколько задач без цели (это **ошибки**
`check`) и сколько без критериев (`check` их ошибкой не считает, но `sprint `check`) и сколько без критериев (`check` их ошибкой не считает, но `ready`
take` такую задачу не возьмёт). Закрывается это **порциями переоценки**шаг 3 такую задачу не пропустит). Закрывается это **порциями груминга**скилл
скилла `session`, 5–8 задач за порцию: проставить цели, превратить «готово, `groom`, 5–8 задач за порцию: проставить цели, превратить «готово, когда» в
когда» в критерии с оракулами, вынуть вопросы из прозы в раздел «Вопросы». критерии с оракулами, вынуть вопросы из прозы в раздел «Вопросы». Там же
беклогу впервые назначается **порядок**: после адаптации его нет вовсе, а
очередь и есть то, ради чего каталог заводят.
Готовность к первому спринту — не «`check` зелёный», а «есть 25 критериев хотя Готовность к первой задаче — не «`check` зелёный», а «`ready` пропускает хотя бы
бы у набора под одну цель». верхние строки очереди».
## Чего адаптация не делает ## Чего адаптация не делает
@@ -109,7 +111,7 @@ take` такую задачу не возьмёт). Закрывается эт
- **Не переписывает подписи ссылок.** `[docs/backlog](tasks/BACKLOG.md)` - **Не переписывает подписи ссылок.** `[docs/backlog](tasks/BACKLOG.md)`
цель поправлена, текст остался; это правится глазами, и таких мест немного. цель поправлена, текст остался; это правится глазами, и таких мест немного.
- **Не сочиняет критерии приёмки и не придумывает цели**, которых в материале - **Не сочиняет критерии приёмки и не придумывает цели**, которых в материале
нет. Придуманная цель хуже отсутствующей: под неё соберут спринт. нет. Придуманная цель хуже отсутствующей: под неё заведут задачи.
- **Не трогает историю.** В коммитах старые слаги остаются, и это нормально. - **Не трогает историю.** В коммитах старые слаги остаются, и это нормально.
## Доклад ## Доклад
@@ -25,7 +25,7 @@
переживает запись. переживает запись.
- **Находка без свидетельства / низкой уверенности** → **сырьё**: `research`, у - **Находка без свидетельства / низкой уверенности** → **сырьё**: `research`, у
которого раздел «Вопрос» и есть недостающее свидетельство («при каких условиях которого раздел «Вопрос» и есть недостающее свидетельство («при каких условиях
это воспроизводится»). Не `fix`: без `Воспроизведения` его в спринт не это воспроизводится»). Не `fix`: без `Воспроизведения` его в работу не
возьмут, и правильно — чинить нечего, пока непонятно, что ломается. Судьба возьмут, и правильно — чинить нечего, пока непонятно, что ломается. Судьба
сырья — штурм, где либо найдётся подтверждение, либо оно уедет в сырья — штурм, где либо найдётся подтверждение, либо оно уедет в
`REJECTED.md`. `REJECTED.md`.
@@ -46,7 +46,7 @@
устареть, выноси пользователю, а не заводи молча заново. устареть, выноси пользователю, а не заводи молча заново.
4. **Разложи по целям — там, где цель нужна.** Большинство находок ревью это 4. **Разложи по целям — там, где цель нужна.** Большинство находок ревью это
`fix` и `chore`, и **цель им не требуется**: они служат работоспособности, а `fix` и `chore`, и **цель им не требуется**: они служат работоспособности, а
не направлению, и в спринт входят помимо его цели. Придуманная им цель — не направлению. Придуманная им цель —
ровно то враньё, от которого спасает тип. ровно то враньё, от которого спасает тип.
Цель обязательна у находки, которая оказалась **новой возможностью** Цель обязательна у находки, которая оказалась **новой возможностью**
@@ -79,13 +79,13 @@
Правило замены: Правило замены:
- **тяжёлая находка со свидетельством** → задача под ту цель, которой она - **тяжёлая находка со свидетельством** → задача под ту цель, которой она
угрожает, и **кандидат в ближайший набор**: серьёзность здесь превращается в угрожает, и **кандидат на верх очереди**: серьёзность здесь превращается в
довод при выборе цели следующего спринта, а не в уровень в файле. Довод довод при расстановке приоритета, а не в уровень в файле. Довод записывается
записывается причиной в мете (`--reason`), иначе к моменту набора его причиной в мете (`--reason`), иначе к моменту груминга его никто не вспомнит.
никто не вспомнит; Саму строку интейк ставит в конец секции: очередь назначает человек;
- **находка, ломающая уже идущий спринт**, — не интейк вовсе: см. правило - **находка, которая не ждёт груминга вовсе** (необратимый ущерб, сломан общий
вторжения в скилле `session`. В беклог она падает, только если врываться не станок), — не интейк: это работа прямо сейчас, а в беклог она падает, только
положено; если ждать всё-таки можно;
- **низкая уверенность или нет свидетельства** → сырьё (`research` с пустым - **низкая уверенность или нет свидетельства** → сырьё (`research` с пустым
разделом «Вопрос»); разделом «Вопрос»);
- **мелочь** → строка в пакетный файл; - **мелочь** → строка в пакетный файл;
@@ -66,13 +66,14 @@
той же целью. Если частям нужен общий заголовок — значит у них общая той же целью. Если частям нужен общий заголовок — значит у них общая
возможность, и её надо назвать целью, а не заводить временный тип. возможность, и её надо назвать целью, а не заводить временный тип.
## Когда декомпозиция случается посреди спринта ## Когда декомпозиция случается посреди работы
Задача, которая **оказалась крупнее задачи**, распознаётся до того, как под неё Задача, которая **оказалась крупнее задачи**, распознаётся до того, как под неё
заведено предложение об изменении: иначе его придётся выбрасывать. Она выходит заведено предложение об изменении: иначе его придётся выбрасывать. Она выходит
из набора (`sprint drop … --reason "крупнее задачи"`), уходит на декомпозицию, а уходит на декомпозицию, а её строка возвращается в беклог с причиной
спринт продолжается остальными. Части заводятся сразу под той же целью, но в (`move … --reason "крупнее задачи"`). Части заводятся сразу под той же целью, и
текущий набор **не добавляются** — набор заморожен. **место в очереди им назначает человек**: машина поставит их в конец секции, а
крупная задача редко распадается на что-то менее срочное, чем была сама.
## Мозговой штурм сырья ## Мозговой штурм сырья
@@ -80,7 +81,7 @@
тест «готова к взятию», потому что неясно, что именно делаем. Штурм проясняет — тест «готова к взятию», потому что неясно, что именно делаем. Штурм проясняет —
и это **generative-операция, а не applicative**. и это **generative-операция, а не applicative**.
Исход штурма и есть заполненный «Вопрос» (тогда разведку можно брать в спринт) Исход штурма и есть заполненный «Вопрос» (тогда разведку можно брать в работу)
или набор задач с типами, которые из ответа следуют. Третий законный исход — или набор задач с типами, которые из ответа следуют. Третий законный исход —
`close --reason`. `close --reason`.
@@ -15,8 +15,8 @@
| Допустимые сверх того | `Рамки`, `Вопросы` | | Допустимые сверх того | `Рамки`, `Вопросы` |
| Поле места | **Категория** — полка домена беклога | | Поле места | **Категория** — полка домена беклога |
| Цель (`goal:<слаг>`) | нет: цель — это возможность, а здесь её не появляется | | Цель (`goal:<слаг>`) | нет: цель — это возможность, а здесь её не появляется |
| Индекс | `BACKLOG.md``SPRINT.md` | | Индекс | `BACKLOG.md` |
| Берётся в спринт | да | | Берётся в работу | да |
## Адресат — разработчик, и это законно ## Адресат — разработчик, и это законно
@@ -49,12 +49,12 @@
(«обновить зависимости и переписать сборку и убрать мёртвый код»). Не («обновить зависимости и переписать сборку и убрать мёртвый код»). Не
мерджится порознь — это несколько задач ([split.md](split.md)). мерджится порознь — это несколько задач ([split.md](split.md)).
6. **Цель не проставлять.** `chore` служит работоспособности, а не направлению, 6. **Цель не проставлять.** `chore` служит работоспособности, а не направлению,
и в набор спринта входит помимо его цели. Работа по сопровождению проекта работоспособности, а не направлению. Работа по сопровождению проекта
при этом видна в роадмапе — секцией `Сопровождение`, но целью не становится. при этом видна в роадмапе — секцией `Сопровождение`, но целью не становится.
## Что видит машина, а что человек ## Что видит машина, а что человек
`check` и `sprint take` смотрят на **наличие непустого** `Затрагивает` и на `check` и `ready` смотрят на **наличие непустого** `Затрагивает` и на
**число** критериев — ровно то же, что у `feature`. Разница между типами здесь не **число** критериев — ровно то же, что у `feature`. Разница между типами здесь не
в строгости проверки, а в том, **кому адресован ответ** на «что станет в строгости проверки, а в том, **кому адресован ответ** на «что станет
наблюдаемо иначе», — и это судит человек. наблюдаемо иначе», — и это судит человек.
@@ -16,12 +16,12 @@
| Допустимые сверх того | `Рамки`, `Вопросы` | | Допустимые сверх того | `Рамки`, `Вопросы` |
| Поле места | **Категория** — полка домена беклога | | Поле места | **Категория** — полка домена беклога |
| Цель (`goal:<слаг>`) | **обязательна** | | Цель (`goal:<слаг>`) | **обязательна** |
| Индекс | `BACKLOG.md``SPRINT.md` | | Индекс | `BACKLOG.md` |
| Берётся в спринт | да | | Берётся в работу | да |
**Цель обязательна, и это единственный тип, у которого так.** Новая возможность **Цель обязательна, и это единственный тип, у которого так.** Новая возможность
и есть содержание цели: подходящей нет — либо она заводится, либо перед тобой не и есть содержание цели: подходящей нет — либо она заводится, либо перед тобой не
`feature`. `sprint take` без цели откажет. `feature`. `ready` без цели откажет.
## Алгоритм ## Алгоритм
@@ -48,7 +48,7 @@
## Что видит машина, а что человек ## Что видит машина, а что человек
`check` и `sprint take` смотрят на **наличие непустого** раздела `Затрагивает`, `check` и `ready` смотрят на **наличие непустого** раздела `Затрагивает`,
на **число** критериев (меньше двух — отказ, больше пяти — замечание) и на цель. на **число** критериев (меньше двух — отказ, больше пяти — замечание) и на цель.
Наличие оракула проверяется **эвристикой** — словом «оракул» в пункте. Наличие оракула проверяется **эвристикой** — словом «оракул» в пункте.
@@ -17,14 +17,14 @@
| Допустимые сверх того | `Рамки`, `Вопросы` | | Допустимые сверх того | `Рамки`, `Вопросы` |
| Поле места | **Категория** — полка домена беклога | | Поле места | **Категория** — полка домена беклога |
| Цель (`goal:<слаг>`) | необязательна | | Цель (`goal:<слаг>`) | необязательна |
| Индекс | `BACKLOG.md``SPRINT.md` | | Индекс | `BACKLOG.md` |
| Берётся в спринт | да | | Берётся в работу | да |
## `Воспроизведение` — раздел, которого нет у других типов ## `Воспроизведение` — раздел, которого нет у других типов
**Не воспроизводится — это `research`, а не `fix`.** Правило было записано и **Не воспроизводится — это `research`, а не `fix`.** Правило было записано и
раньше, но проверять его было нечем, и «починки» без единого шага повторения раньше, но проверять его было нечем, и «починки» без единого шага повторения
уходили в спринт наравне с остальными. Раздел делает правило проверяемым: он уходили в работу наравне с остальными. Раздел делает правило проверяемым: он
называет, **что сделать, чтобы расхождение проявилось, и что при этом видно называет, **что сделать, чтобы расхождение проявилось, и что при этом видно
вместо ожидаемого**. вместо ожидаемого**.
@@ -55,7 +55,7 @@
(«ввод `а1` принимается по-прежнему»). Без него починка чинит одно и ломает («ввод `а1` принимается по-прежнему»). Без него починка чинит одно и ломает
соседнее. соседнее.
6. **Цель не выдумывать.** `fix` служит работоспособности, а не направлению, и в 6. **Цель не выдумывать.** `fix` служит работоспособности, а не направлению, и в
набор спринта входит помимо его цели. Придуманная цель — то же враньё, от работоспособности, а не направлению. Придуманная цель — то же враньё, от
которого спасает тип. которого спасает тип.
7. **Записать дефект в журнал** `docs/review.md` с пометкой «проскочил / пойман 7. **Записать дефект в журнал** `docs/review.md` с пометкой «проскочил / пойман
ревью». Проскочившие — проверочный набор для калибровки конвейера; пойманные с ревью». Проскочившие — проверочный набор для калибровки конвейера; пойманные с
@@ -64,7 +64,7 @@
## Что видит машина, а что человек ## Что видит машина, а что человек
`check` и `sprint take` смотрят на **наличие непустого** `Воспроизведения` и `check` и `ready` смотрят на **наличие непустого** `Воспроизведения` и
`Затрагивает` и на **число** критериев. Годность воспроизведения — человеку: `Затрагивает` и на **число** критериев. Годность воспроизведения — человеку:
шаги, по которым ничего не воспроизводится, машина от годных не отличает, и шаги, по которым ничего не воспроизводится, машина от годных не отличает, и
делать вид, что проверено больше проверенного, хуже, чем не проверять вовсе. делать вид, что проверено больше проверенного, хуже, чем не проверять вовсе.
@@ -23,9 +23,9 @@
# 🐞 Не отбрасывать молча лишние символы в ходе # 🐞 Не отбрасывать молча лишние символы в ходе
- **Тип:** fix - **Тип:** fix
- **Категория:** Ядро — вышла из спринта: остаток писал нерешённое в журнал - **Категория:** Ядро — вернулась из работы: остаток писал нерешённое в журнал
- **Зачем:** ввод «а1б2» ходит в a1 — игрок не видит, что ошибся, и винит игру - **Зачем:** ввод «а1б2» ходит в a1 — игрок не видит, что ошибся, и винит игру
- **Теги:** goal:merge-robustness, sprint:2026-08-03 - **Теги:** goal:merge-robustness
Разбор хода читает первые два символа и молча выбрасывает остаток строки. Разбор хода читает первые два символа и молча выбрасывает остаток строки.
@@ -63,11 +63,11 @@
здоровье; годность формулировки смотрит агент `task-form`. здоровье; годность формулировки смотрит агент `task-form`.
- **Мета-блок** — список сразу после заголовка, **поле на строку**. Обязательны - **Мета-блок** — список сразу после заголовка, **поле на строку**. Обязательны
**тип** и **место**, причина после тире желательна (именно она объясняет, **тип** и **место**, причина после тире желательна (именно она объясняет,
почему задача здесь оказалась — в том числе «вышла из спринта: …»), «зачем» и почему задача здесь оказалась — в том числе «вернулась из работы: …»), «зачем» и
теги необязательны. Нераспознанные поля сохраняются: скрипт правит свои и не теги необязательны. Нераспознанные поля сохраняются: скрипт правит свои и не
трогает чужие. трогает чужие.
- **Тип — первым полем.** Он решает, что у записи вообще может быть: какие - **Тип — первым полем.** Он решает, что у записи вообще может быть: какие
разделы обязательны, нужна ли цель, берётся ли она в спринт, — и читается разделы обязательны, нужна ли цель, берётся ли она в работу, — и читается
раньше всего остального. Словарь **закрыт**: `goal` | `feature` | `fix` | раньше всего остального. Словарь **закрыт**: `goal` | `feature` | `fix` |
`chore` | `research`. Не подходит ни один — это сигнал, что в записи их два и `chore` | `research`. Не подходит ни один — это сигнал, что в записи их два и
её надо разделить. её надо разделить.
@@ -93,11 +93,11 @@
| Тип | Поле | Значения | Что это | | Тип | Поле | Значения | Что это |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `goal` | **Секция** | `Запланировано`, `Направления`, `Сопровождение` | часть роадмапа: состояние очереди | | `goal` | **Секция** | `Запланировано`, `Направления`, `Сопровождение` | часть роадмапа: состояние очереди |
| прочие | **Категория** | секции беклога проекта (`Ядро`, `Инфра`, …) | полка домена, в которую задача вернётся из спринта | | прочие | **Категория** | секции беклога проекта (`Ядро`, `Инфра`, …) | полка домена, на которой задача лежит |
Разные имена потому, что это **разные вещи**. У задачи поле переживает спринт: Разные имена потому, что это **разные вещи**. У задачи это полка: куда её
`sprint drop` возвращает её именно туда. У цели оно называет не полку, а место в положили и куда вернут, если она уйдёт в работу и вернётся. У цели оно называет
очереди работ. Одно имя на два смысла их и смешивало; `check` называет не полку, а место в очереди работ. Одно имя на два смысла их и смешивало; `check` называет
несовпадение дрейфом, `check --fix` переименовывает. несовпадение дрейфом, `check --fix` переименовывает.
Имя самого места принадлежит **заголовку индекса** — файл на него лишь Имя самого места принадлежит **заголовку индекса** — файл на него лишь
@@ -142,7 +142,7 @@
имя таблицы стабильно, номер последней миграции протухает молча. Пишется имя таблицы стабильно, номер последней миграции протухает молча. Пишется
`таблица points и её миграция`, а не `миграция 0042`. `таблица points и её миграция`, а не `миграция 0042`.
**Что из этого механизировано.** `check` и `sprint take` смотрят только на **Что из этого механизировано.** `check` и `ready` смотрят только на
**наличие непустого раздела**. Полнота перечня машине не видна: границу, которую **наличие непустого раздела**. Полнота перечня машине не видна: границу, которую
забыли назвать, она от отсутствующей не отличает. Раздела нет — отказ во взятии: забыли назвать, она от отсутствующей не отличает. Раздела нет — отказ во взятии:
оценивать нечем. оценивать нечем.
@@ -158,7 +158,7 @@
конкретизация вопроса «по чему видно, что закончено» из теста готовности ниже: конкретизация вопроса «по чему видно, что закончено» из теста готовности ниже:
там сказано «признак завершённости», здесь — «признак плюс чем проверяется». там сказано «признак завершённости», здесь — «признак плюс чем проверяется».
**Что из этого механизировано.** `check` и `sprint take` считают пункты: меньше **Что из этого механизировано.** `check` и `ready` считают пункты: меньше
двух — отказ («— работает» одной строкой больше не проходит), больше пяти — двух — отказ («— работает» одной строкой больше не проходит), больше пяти —
замечание, обычно это признак, что задача крупнее задачи. Наличие оракула замечание, обычно это признак, что задача крупнее задачи. Наличие оракула
проверяется **эвристикой** — словом «оракул» в пункте, — и потому даёт только проверяется **эвристикой** — словом «оракул» в пункте, — и потому даёт только
@@ -205,8 +205,8 @@
ответом. Затем снимается тег (`edit <slug> --rm-tag question`) и переписывается ответом. Затем снимается тег (`edit <slug> --rm-tag question`) и переписывается
«зачем»: «Решено: …» на вопрос «зачем нужна эта задача» уже не отвечает. «зачем»: «Решено: …» на вопрос «зачем нужна эта задача» уже не отвечает.
**Порядок именно такой, потому что судит раздел, а не тег.** `sprint take` **Порядок именно такой, потому что судит раздел, а не тег.** `ready`
смотрит в непустой раздел и откажет взять задачу даже со снятым тегом, а `check` смотрит в непустой раздел и откажет даже при снятом теге, а `check`
на снятый тег при непустом разделе посоветует тег вернуть. Снять тег, не на снятый тег при непустом разделе посоветует тег вернуть. Снять тег, не
опустошив раздел, — значит закольцевать себя между двумя советами. опустошив раздел, — значит закольцевать себя между двумя советами.
@@ -240,7 +240,7 @@
`check` напоминает о нём у цели без задач замечанием — неразобранная цель `check` напоминает о нём у цели без задач замечанием — неразобранная цель
законна и зелёного прогона не ломает; `check --fix` сам ставит его цели, у законна и зелёного прогона не ломает; `check --fix` сам ставит его цели, у
которой задачи есть, а цель с тегом и без задач — прямое приглашение закрыть. которой задачи есть, а цель с тегом и без задач — прямое приглашение закрыть.
- Цель живёт в `ROADMAP.md` и **никогда** — в `BACKLOG.md` или `SPRINT.md`. - Цель живёт в `ROADMAP.md` и **никогда** — в `BACKLOG.md`.
- **Достигнутая цель не исчезает.** `close <слаг> --implemented` удаляет файл и - **Достигнутая цель не исчезает.** `close <слаг> --implemented` удаляет файл и
переносит строку в секцию `Готово` с датой: переносит строку в секцию `Готово` с датой:
`- 2026-08-04 \`merge-order\` — Исход слияния не зависит от порядка доставки. …` `- 2026-08-04 \`merge-order\` — Исход слияния не зависит от порядка доставки. …`
@@ -277,33 +277,23 @@
| Файл | Что отвечает | Секции | | Файл | Что отвечает | Секции |
| --- | --- | --- | | --- | --- | --- |
| `ROADMAP.md` | что приложение уже умеет и чего ещё не умеет | канонические и в этом порядке: `Запланировано`, `Направления`, `Сопровождение`, `Готово` (англ. `Planned`, `Directions`, `Operations`, `Done`) | | `ROADMAP.md` | что приложение уже умеет и чего ещё не умеет | канонические и в этом порядке: `Запланировано`, `Направления`, `Сопровождение`, `Готово` (англ. `Planned`, `Directions`, `Operations`, `Done`) |
| `BACKLOG.md` | что **можно взять** — только задачи | категории проекта (по умолчанию Ядро/Инфра) | | `BACKLOG.md` | что **можно взять** — только задачи, **в порядке очереди** | категории проекта (по умолчанию Ядро/Инфра) |
| `SPRINT.md` | какая цель (или что её нет) и какой набор заморожен | одна: «Набор» |
| `REJECTED.md` | что ушло без реализации и почему | — | | `REJECTED.md` | что ушло без реализации и почему | — |
Шапку `SPRINT.md` пишет `sprint start` — **тем же мета-блоком, что у задачи**:
поле на строку, `- **Цель:** [Заголовок](items/slug.md)`, `- **Начат:**` датой,
`- **Спринт:**` слагом, которым метится урожай. У спринта без цели
(`sprint start --no-goal`) поле «Цель» остаётся на месте и пишется прозой без
ссылки — «не названа»: **«цели нет» и «цель потерялась» обязаны различаться**.
Поэтому и признак «спринт идёт» — слаг, а не цель: слаг есть у любого спринта,
без него нечем метить урожай. Прежняя форма (три поля одной
строкой через `·`) читается по-прежнему и уходит сама: файл переписывается на
следующем `sprint start` и очищается на `sprint close`.
Секции — **единственные заголовки `##` в индексе**: любой другой `##` в Секции — **единственные заголовки `##` в индексе**: любой другой `##` в
преамбуле проверка сочтёт секцией. преамбуле проверка сочтёт секцией.
**Порядка «по важности» внутри секции беклога нет** — «что делать дальше» **Порядок строк внутри секции беклога значим: это очередь.** Первая строка — то,
отвечает набор спринта. Единственный порядок, который есть, **производен от типа что делают следующим; назначает порядок человек на груминге, и двигают его
и заполненности**: **сырьё** (`research` без раздела «Вопрос») стоит в конце `move --after` и `move --first`. Одно место из очереди изъято и **производно от
типа и заполненности**: **сырьё** (`research` без раздела «Вопрос») стоит в конце
своей секции, потому что его не берут, и между берущимся оно каждый раз требует своей секции, потому что его не берут, и между берущимся оно каждый раз требует
открыть файл, чтобы это понять. Проверяет `check`, переставляет `check --fix`, открыть файл, чтобы это понять. Проверяет `check`, переставляет `check --fix`,
и человек этот порядок не назначает — иначе он был бы приоритетом, которого и человек этот порядок не назначает — иначе он был бы приоритетом, которого
здесь нет. здесь нет.
**Секции «блокеры» среди них нет.** Блокер — состояние, а не полка: он живёт до **Секции «блокеры» среди них нет.** Блокер — состояние, а не полка: он живёт до
ответа человека, а следы остаются вопросами в файлах задач распущенного спринта. ответа человека, а следы остаются вопросами в файлах задач.
Постоянно пустая секция со старой семантикой «разбираются пачками» противоречила Постоянно пустая секция со старой семантикой «разбираются пачками» противоречила
бы правилу «эскалируем немедленно», поэтому `init` её не заводит, а `check` бы правилу «эскалируем немедленно», поэтому `init` её не заводит, а `check`
говорит о ней в чужом беклоге. Переезжаешь с такой секцией — удали её. В секции говорит о ней в чужом беклоге. Переезжаешь с такой секцией — удали её. В секции
@@ -333,9 +323,6 @@ SKILL.md. Порядок закреплён потому, что `Готово`
Поэтому отказ на второй задаче из пяти не оставляет первую переписанной при Поэтому отказ на второй задаче из пяти не оставляет первую переписанной при
нетронутых индексах. нетронутых индексах.
`SPRINT.md` и есть артефакт заморозки: без него набор существует только в
контексте сессии, и нарушение заморозки ненаблюдаемо.
## `REJECTED.md` ## `REJECTED.md`
Туда уходит задача, покинувшая беклог **без реализации**. Строку пишет Туда уходит задача, покинувшая беклог **без реализации**. Строку пишет
@@ -361,15 +348,8 @@ SKILL.md. Порядок закреплён потому, что `Готово`
- `goal:<слаг>` — цель, которой служит задача. Обязателен **у `feature`**: - `goal:<слаг>` — цель, которой служит задача. Обязателен **у `feature`**:
новая возможность и есть содержание цели. У `fix`, `chore` и `research` его новая возможность и есть содержание цели. У `fix`, `chore` и `research` его
может не быть — они служат работоспособности, а не направлению, и в набор может не быть — они служат работоспособности, а не направлению.
спринта входят помимо его цели.
- `question` — в файле есть неразобранный раздел «Вопросы». - `question` — в файле есть неразобранный раздел «Вопросы».
- `sprint:<слаг>` — задача заведена в этом спринте; по нему отбирается первая
порция разбора («урожай спринта»). **Ставится сам**: слаг спринта заводит
`sprint start` (по умолчанию — дата начала, он же пишется в `SPRINT.md`), и
`add` при открытом спринте помечает заводимое. Тег, который надо помнить
ставить руками, не ставится никогда — а на нём висит правило «первая порция
разбора — урожай прошедшего спринта».
- `decomposed` — на цели: разложена на задачи (см. «Файл цели»). - `decomposed` — на цели: разложена на задачи (см. «Файл цели»).
Тега `kind:<род>` больше нет: род работы стал типом. Оставшийся в файле `check` Тега `kind:<род>` больше нет: род работы стал типом. Оставшийся в файле `check`
@@ -16,11 +16,11 @@
| Допустимые сверх того | — | | Допустимые сверх того | — |
| Поле места | **Секция** — часть роадмапа | | Поле места | **Секция** — часть роадмапа |
| Цель (`goal:<слаг>`) | запрещена: цель и есть цель | | Цель (`goal:<слаг>`) | запрещена: цель и есть цель |
| Индекс | `ROADMAP.md`, и никогда `BACKLOG.md` или `SPRINT.md` | | Индекс | `ROADMAP.md`, и никогда `BACKLOG.md` |
| Берётся в спринт | нет — берутся её задачи | | Берётся в работу | нет — берутся её задачи |
Поле места у цели называется **«Секция»**, а не «Категория», и это не разнобой: Поле места у цели называется **«Секция»**, а не «Категория», и это не разнобой:
у задачи оно называет полку домена, в которую она вернётся из спринта, а у цели у задачи оно называет полку домена, на которой она лежит, а у цели
— часть роадмапа, то есть состояние очереди. Одно имя на два смысла их и — часть роадмапа, то есть состояние очереди. Одно имя на два смысла их и
смешивало. смешивало.
@@ -77,7 +77,7 @@
**Место этому — переоценка на сессии, а не отдельный заход.** Отмена цели значит **Место этому — переоценка на сессии, а не отдельный заход.** Отмена цели значит
разбор всех её задач, а разбор задач и есть шаг 3 сессии разбор всех её задач, а разбор задач и есть шаг 3 сессии
([cadence.md](../../session/references/cadence.md), пункт 7). Отменять на ходу, (скилл `groom`, разбор «что перестало быть важным»). Отменять на ходу,
между делом, — верный способ закрыть скопом то, что стоило перевесить. между делом, — верный способ закрыть скопом то, что стоило перевесить.
## Что видит машина, а что человек ## Что видит машина, а что человек
@@ -15,8 +15,8 @@
| Допустимые сверх того | `Рамки`, `Вопросы` | | Допустимые сверх того | `Рамки`, `Вопросы` |
| Поле места | **Категория** — полка домена беклога | | Поле места | **Категория** — полка домена беклога |
| Цель (`goal:<слаг>`) | нет | | Цель (`goal:<слаг>`) | нет |
| Индекс | `BACKLOG.md``SPRINT.md` | | Индекс | `BACKLOG.md` |
| Берётся в спринт | да — **но только с заполненным «Вопросом»** | | Берётся в работу | да — **но только с заполненным «Вопросом»** |
**Критериев приёмки у `research` нет, и это не поблажка.** Критерии в форме **Критериев приёмки у `research` нет, и это не поблажка.** Критерии в форме
«оракул: тест» разведке натянуты: проверять нечего, пока ответа нет. Её приёмка «оракул: тест» разведке натянуты: проверять нечего, пока ответа нет. Её приёмка
@@ -39,13 +39,14 @@
| | сырьё | разведка | | | сырьё | разведка |
| --- | --- | --- | | --- | --- | --- |
| Раздел `Вопрос` | пуст или отсутствует | заполнен | | Раздел `Вопрос` | пуст или отсутствует | заполнен |
| `sprint take` | отказ | берёт | | `ready` | отказ | берёт |
| Место в секции беклога | **конец**, `check --fix` сносит туда сам | среди прочих | | Место в секции беклога | **конец**, `check --fix` сносит туда сам | среди прочих |
| `tasks.py list --raw` | показывает | нет | | `tasks.py list --raw` | показывает | нет |
Порядка «по важности» в беклоге по-прежнему нет. Этот порядок **производен от Порядок строк в беклоге назначает человек — это приоритет (правило 4 скилла).
типа и заполненности**, а не назначен человеком, — потому его и проверяет машина, Место сырья **из него изъято**: оно производно от типа и заполненности, а не от
и потому он не противоречит правилу «порядка нет, есть цель». чьего-то решения, и потому его проверяет и чинит машина. Приоритетом оно не
становится: сырьё не берут вовсе, и место в конце говорит именно это.
Сырьём заводится и **сырая функция**: «Подсказка следующего хода» — ещё не Сырьём заводится и **сырая функция**: «Подсказка следующего хода» — ещё не
`feature`, потому что неизвестно, что именно делать. Работа над ней — думание, и `feature`, потому что неизвестно, что именно делать. Работа над ней — думание, и
@@ -67,14 +68,14 @@
проход ревью обязан читать как условие, а не как замер. проход ревью обязан читать как условие, а не как замер.
5. **Разложить исход на задачи** — если он их родил. Разведка кончается одним из 5. **Разложить исход на задачи** — если он их родил. Разведка кончается одним из
трёх: заведены задачи, записано знание, отказ. **Отказ — полноправный исход**: трёх: заведены задачи, записано знание, отказ. **Отказ — полноправный исход**:
«проверили, не проблема» экономит спринт. «проверили, не проблема» экономит работу.
6. **Закрыть**`close <слаг> --implemented`, когда ответ записан. Файл 6. **Закрыть**`close <слаг> --implemented`, когда ответ записан. Файл
удаляется: запись ответа и есть след, второго не нужно. Ушла без ответа — удаляется: запись ответа и есть след, второго не нужно. Ушла без ответа —
`close --reason`, и строка уезжает в `REJECTED.md`. `close --reason`, и строка уезжает в `REJECTED.md`.
## Что видит машина, а что человек ## Что видит машина, а что человек
`check` и `sprint take` смотрят на **наличие непустых** разделов `Вопрос` и `check` и `ready` смотрят на **наличие непустых** разделов `Вопрос` и
`Куда ляжет ответ`, считают сырьё отдельной строкой здоровья и держат его в конце `Куда ляжет ответ`, считают сырьё отдельной строкой здоровья и держат его в конце
секции. Годность вопроса — человеку: «вопрос это или тема» машина не различает, секции. Годность вопроса — человеку: «вопрос это или тема» машина не различает,
и `check` о годности молчит намеренно. и `check` о годности молчит намеренно.
+1 -1
View File
@@ -3012,7 +3012,7 @@ def cmd_adopt_apply(a: argparse.Namespace) -> int:
print(f" задач, не собравших разделы своего типа: {len(unfit)}" print(f" задач, не собравших разделы своего типа: {len(unfit)}"
f" check это ошибкой не считает, но `ready` их не пропустит:" f" check это ошибкой не считает, но `ready` их не пропустит:"
f" брать сегодня физически нечего") f" брать сегодня физически нечего")
print(f" закрывается порциями переоценки по 5–8 задач (скилл session, шаг 3):" print(f" закрывается порциями груминга по 5–8 задач (скилл groom):"
f" проставить цели, превратить «готово, когда» в критерии с оракулами," f" проставить цели, превратить «готово, когда» в критерии с оракулами,"
f" вынуть вопросы из прозы в раздел. Готовность к первой задаче —" f" вынуть вопросы из прозы в раздел. Готовность к первой задаче —"
f" не «check зелёный», а «есть {CRITERIA_MIN}+ критериев хотя бы у набора" f" не «check зелёный», а «есть {CRITERIA_MIN}+ критериев хотя бы у набора"