канон 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:
@@ -1,78 +1,125 @@
|
||||
# Формат задач, целей и индексов
|
||||
# Формат записей и индексов
|
||||
|
||||
Заголовок, мета-блок и строку индекса ставит `tasks.py add` — руками их не
|
||||
пишут. Этот файл описывает, что именно скрипт создаёт и что проверяет `check`;
|
||||
тело задачи (одну фразу, критерии, рамки, контекст) дописывает агент.
|
||||
пишут. Этот файл описывает **общую форму** любой записи и то, что проверяет
|
||||
`check`; тело дописывает агент.
|
||||
|
||||
## Файл задачи
|
||||
Чем разделы тела отличаются от типа к типу, какой алгоритм у каждого типа и что
|
||||
у него обязательно — **отдельным файлом на тип**:
|
||||
|
||||
| Тип | Файл | Одной строкой |
|
||||
| --- | --- | --- |
|
||||
| 🎯 `goal` | [task-goal.md](task-goal.md) | возможность приложения |
|
||||
| ✨ `feature` | [task-feature.md](task-feature.md) | снаружи появляется то, чего не было |
|
||||
| 🐞 `fix` | [task-fix.md](task-fix.md) | поведение расходится с заявленным |
|
||||
| 🧹 `chore` | [task-chore.md](task-chore.md) | обслуживание, поведение не меняется |
|
||||
| 🔬 `research` | [task-research.md](task-research.md) | исход — знание, а не изменение |
|
||||
|
||||
## Файл записи
|
||||
|
||||
`items/<slug>.md`:
|
||||
|
||||
```markdown
|
||||
# Тай-брейк при равной полноте
|
||||
# 🐞 Не отбрасывать молча лишние символы в ходе
|
||||
|
||||
- **Секция:** Ядро — вышла из спринта: остаток писал нерешённое в журнал
|
||||
- **Зачем:** порядок канонических форм берёт меньшее в 96% случаев — для накопительных это систематический недосчёт
|
||||
- **Теги:** goal:merge-robustness, kind:fix, sprint:2026-08-03
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро — вышла из спринта: остаток писал нерешённое в журнал
|
||||
- **Зачем:** ввод «а1б2» ходит в a1 — игрок не видит, что ошибся, и винит игру
|
||||
- **Теги:** goal:merge-robustness, sprint:2026-08-03
|
||||
|
||||
При столкновении точек выигрывает более полная, но при равной полноте побеждает
|
||||
последняя доставка — а она систематически беднее первой.
|
||||
Разбор хода читает первые два символа и молча выбрасывает остаток строки.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
Ввести `а1б2` в свой ход: программа ходит в `a1` и ничего не сообщает.
|
||||
Ожидалось — отказ с ошибкой разбора.
|
||||
|
||||
## Затрагивает
|
||||
|
||||
Таблица `points` и её миграция; правило слияния в приёме доставки; формат
|
||||
отпечатка состояния на диске. Публичного контракта не трогает.
|
||||
Разбор строки хода; текст ошибки в выводе партии. Формат сохранения партии
|
||||
не трогается.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- повторный прогон свёртки даёт тот же отпечаток состояния — оракул: команда сверки
|
||||
- накопительная метрика за сутки не уменьшается после повторной доставки — оракул: тест
|
||||
- в логе видно, какая из двух точек выиграла и почему — оракул: глазами по логу прогона
|
||||
- ввод «а1б2» отвергается с ошибкой — оракул: тест разбора
|
||||
- ввод «а1» принимается по-прежнему — оракул: тест разбора
|
||||
|
||||
## Рамки
|
||||
|
||||
Схема не трогается; данные только читаются; перезапуск сервиса допустим.
|
||||
Схема не трогается; данные только читаются; перезапуск допустим.
|
||||
|
||||
Связано: решение о канонической форме содержимого.
|
||||
```
|
||||
|
||||
- **Заголовок H1** — он же заголовок строки в индексе, дословно. Тип кодируется
|
||||
префиксом `[goal]` / `[idea]`; обычная задача — без префикса.
|
||||
Отдельного поля типа **нет**: два места для одного факта разъезжаются, а
|
||||
префикс виден прямо в индексе, где и принимается решение «брать или не брать».
|
||||
- **Форма заголовка — по типу записи.** Задача отвечает на «что нужно сделать»
|
||||
и пишется глаголом в неопределённой форме («Печатать поле одним куском кода»,
|
||||
«Не отбрасывать молча лишние символы»); цель — на «что приложение будет
|
||||
уметь»; идея просто называет, о чём она. Почему так — SKILL.md, «Как написана
|
||||
- **Заголовок H1** — он же заголовок строки в индексе, дословно. Начинается
|
||||
**эмодзи типа**, и она **производна**: её ставит `add` и чинит `check --fix`
|
||||
по полю меты. Второго дома у типа нет — эмодзи это его отображение, как
|
||||
строка индекса это отображение файла.
|
||||
- **Форма заголовка — по типу.** Цель отвечает на «что приложение будет уметь»;
|
||||
`feature`, `fix` и `chore` — на «что нужно сделать», глаголом в неопределённой
|
||||
форме, перед ним допускается «не»; `research` называет предмет разведки и
|
||||
формы действия **не несёт намеренно**. Почему так — SKILL.md, «Как написана
|
||||
задача». `check` считает заголовки не в форме действия и печатает число в
|
||||
здоровье; годность формулировки смотрит агент `task-form`.
|
||||
- **Мета-блок** — список сразу после заголовка, **поле на строку**. Обязательна
|
||||
секция, причина после тире желательна (именно она объясняет, почему задача
|
||||
здесь оказалась — в том числе «вышла из спринта: …»), «зачем» и теги
|
||||
опциональны. Порядок свободный, поле в одну строку. Нераспознанные поля
|
||||
сохраняются: скрипт правит свои и не трогает чужие.
|
||||
- **Мета-блок** — список сразу после заголовка, **поле на строку**. Обязательны
|
||||
**тип** и **место**, причина после тире желательна (именно она объясняет,
|
||||
почему задача здесь оказалась — в том числе «вышла из спринта: …»), «зачем» и
|
||||
теги опциональны. Нераспознанные поля сохраняются: скрипт правит свои и не
|
||||
трогает чужие.
|
||||
- **Тип — первым полем.** Он решает, что у записи вообще может быть: какие
|
||||
разделы обязательны, нужна ли цель, берётся ли она в спринт, — и читается
|
||||
раньше всего остального. Словарь **закрыт**: `goal` | `feature` | `fix` |
|
||||
`chore` | `research`. Не подходит ни один — это сигнал, что в записи их два и
|
||||
её надо разделить.
|
||||
- **«Зачем» отвечает на «зачем нужна эта задача»** — состояние, остаток, боль.
|
||||
Не пересказ задачи: пересказ уже есть по ссылке. Живёт здесь, а не только в
|
||||
индексе: строка индекса его повторяет и производна от него, `check` сверяет,
|
||||
`check --fix` восстанавливает пропавшую строку **вместе с ним**. Пока поле
|
||||
лежало только в индексе, штатная починка дрейфа теряла его молча и
|
||||
навсегда — а это единственное, по чему задачу выбирают, не открывая.
|
||||
|
||||
- **Тело** — одна фраза «что станет наблюдаемо иначе», затрагиваемые границы,
|
||||
критерии приёмки, рамки, контекст, ссылки. Пишется на языке документации
|
||||
проекта: предметно, без англицизмов, у которых есть русское слово, и без
|
||||
терминов, которых нет ни в паспорте, ни в архитектуре, ни в конвенциях
|
||||
(правило и его причина — в SKILL.md, раздел «Как написана задача»).
|
||||
|
||||
Мета **одной строкой через `·`** — прежняя форма. Она читается по-прежнему,
|
||||
`check` называет её дрейфом, `check --fix` переписывает списком; поле `Хук`
|
||||
при этом становится `Зачем`. Причина отказа от строки простая: с тремя полями
|
||||
и длинным «зачем» строка уезжала за экран, а `·` приходилось запрещать в тексте
|
||||
причины и самого «зачем».
|
||||
- **Тело** — одна фраза «что станет наблюдаемо иначе», дальше разделы по схеме
|
||||
типа. Пишется на языке документации проекта: предметно, без англицизмов, у
|
||||
которых есть русское слово, и без терминов, которых нет ни в паспорте, ни в
|
||||
архитектуре, ни в конвенциях (правило и его причина — в SKILL.md, раздел «Как
|
||||
написана задача»).
|
||||
|
||||
Тело — не план реализации и не спецификация: принятое и реализованное переезжает
|
||||
в документацию проекта, а файл задачи удаляется.
|
||||
|
||||
### Поле места: «Категория» и «Секция»
|
||||
|
||||
Поле называет, **где числится строка**, и имя у него **зависит от типа**:
|
||||
|
||||
| Тип | Поле | Значения | Что это |
|
||||
| --- | --- | --- | --- |
|
||||
| `goal` | **Секция** | `Запланировано`, `Направления`, `Сопровождение` | часть роадмапа: состояние очереди |
|
||||
| прочие | **Категория** | секции беклога проекта (`Ядро`, `Инфра`, …) | полка домена, в которую задача вернётся из спринта |
|
||||
|
||||
Разные имена потому, что это **разные вещи**. У задачи поле переживает спринт:
|
||||
`sprint drop` возвращает её именно туда. У цели оно называет не полку, а место в
|
||||
очереди работ. Одно имя на два смысла и было конфляцией; `check` называет
|
||||
несовпадение дрейфом, `check --fix` переименовывает.
|
||||
|
||||
Имя самого места принадлежит **заголовку индекса** — файл на него лишь
|
||||
ссылается, и принадлежность сверяется по нижнему регистру.
|
||||
|
||||
### Прежние формы, которые читаются, но не пишутся
|
||||
|
||||
Всё это `check` называет дрейфом, а `check --fix` переписывает:
|
||||
|
||||
| Было | Стало |
|
||||
| --- | --- |
|
||||
| префикс `[goal]` / `[idea]` в H1 | поле **Тип** + эмодзи в H1; `[idea]` → `research` |
|
||||
| тег `kind:<род>` | поле **Тип** (род работы стал типом) |
|
||||
| поле **Секция** у задачи | поле **Категория** |
|
||||
| поле **Хук** | поле **Зачем** |
|
||||
| мета одной строкой через `·` | мета списком, поле на строку |
|
||||
|
||||
Единственное, чего `--fix` не делает сам, — **проставить тип записи, у которой
|
||||
его неоткуда взять**: `feature` от `chore` машина не отличает, и подставленное
|
||||
наугад значение врало бы ровно там, где по нему принимают решение. Такие записи
|
||||
он называет поимённо пометкой `НЕОДНОЗНАЧНО`.
|
||||
|
||||
### Затрагивает
|
||||
|
||||
Перечень **границ**, которых изменение касается. Границей считается то, у чего
|
||||
@@ -100,8 +147,8 @@
|
||||
забыли назвать, она от отсутствующей не отличает. Раздела нет — отказ во взятии:
|
||||
оценивать нечем.
|
||||
|
||||
**У идей раздела нет** — как и критериев: границы становятся известны, когда идея
|
||||
превращается в задачу.
|
||||
**У `goal` и `research` раздела нет** — у первой границы называют её задачи, у
|
||||
второй они становятся известны, когда из разведки родятся задачи.
|
||||
|
||||
### Критерии приёмки
|
||||
|
||||
@@ -118,7 +165,9 @@
|
||||
замечание: настоящий оракул от слова «оракул» машина не отличает, и делать вид,
|
||||
что проверено больше проверенного, хуже, чем не проверять вовсе.
|
||||
|
||||
**У идей критериев нет — именно поэтому они идеи.**
|
||||
**У `research` критериев нет** — её приёмка это записанный ответ, и описывается
|
||||
она разделами «Вопрос» и «Куда ляжет ответ». **У `goal` их заменяет
|
||||
«Завершение».**
|
||||
|
||||
**Критерии — пол, но расхождение с ними есть дефект критериев.** Если приёмщик
|
||||
видит, что критерии закрыты, а суть задачи не достигнута, он **правит критерии и
|
||||
@@ -129,16 +178,21 @@
|
||||
### Рамки
|
||||
|
||||
Одна строка: чего касаться нельзя, что перезапускается, что считается
|
||||
необратимым, трогается ли схема данных. **Свойства репозитория сюда не пишутся**
|
||||
— номер последней миграции, версия зависимости, хеш: в лежалой задаче они
|
||||
протухают молча и становятся ложной рамкой. Снимок берётся при постановке, а не
|
||||
при заведении.
|
||||
необратимым, трогается ли схема данных. Раздел **допустим у любого типа задачи и
|
||||
ни у одного не обязателен**. **Свойства репозитория сюда не пишутся** — номер
|
||||
последней миграции, версия зависимости, хеш: в лежалой задаче они протухают
|
||||
молча и становятся ложной рамкой. Снимок берётся при постановке, а не при
|
||||
заведении.
|
||||
|
||||
### Вопросы
|
||||
|
||||
Неразобранное решение человека живёт разделом `## Вопросы` **плюс тегом
|
||||
`question`**. Раздел без тега или тег без раздела — дрейф, `check` о нём скажет.
|
||||
|
||||
Раздел `Вопросы` (о решении человека) и раздел `Вопрос` у `research` (предмет
|
||||
разведки) — **разные вещи и разные слова**: первый блокирует взятие, второй его
|
||||
разрешает.
|
||||
|
||||
**Судит факт, а не метка.** Отказ во взятии даёт **непустой раздел «Вопросы»**,
|
||||
независимо от того, стоит ли тег: иначе забывший тег проходил бы, а поставивший
|
||||
спотыкался — стимул ровно обратный записанному правилу. Тег производен: он нужен
|
||||
@@ -158,13 +212,12 @@
|
||||
|
||||
## Файл цели
|
||||
|
||||
**Заголовок цели отвечает на «что приложение будет уметь».** Не область работ и
|
||||
не имя подсистемы: не «Работа со слиянием», а «Исход слияния не зависит от
|
||||
порядка доставки». Свойство поведения — тоже возможность.
|
||||
Форма та же, разделы и алгоритм — [task-goal.md](task-goal.md).
|
||||
|
||||
```markdown
|
||||
# [goal] Исход слияния не зависит от порядка доставки
|
||||
# 🎯 Исход слияния не зависит от порядка доставки
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Направления
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -181,10 +234,6 @@
|
||||
- **Задачи цели здесь не перечисляются.** Перечень даёт
|
||||
`tasks.py list --goal <слаг>`; хранимый список стал бы третьим индексом и
|
||||
поехал бы на первой же закрытой задаче.
|
||||
- **Раздел «Завершение» — списком, а не абзацем.** Это признаки того, что
|
||||
приложение уже умеет; **на строку «Завершения» ссылается задача**, объясняя,
|
||||
какую часть возможности она двигает (см. тест готовности). Абзацем такая
|
||||
ссылка не берётся, поэтому список.
|
||||
- **Тег `decomposed`** отличает «цель ещё не разобрана» от «все её задачи
|
||||
закрыты» — два состояния, у которых снаружи один и тот же признак: задач нет.
|
||||
Пометка именно **тегом**, а не строкой в теле: только так она проверяется.
|
||||
@@ -217,16 +266,18 @@
|
||||
Строка везде одной формы:
|
||||
|
||||
```markdown
|
||||
- [Заголовок дословно](items/slug.md) — зачем
|
||||
- [🐞 Заголовок дословно](items/slug.md) — зачем
|
||||
```
|
||||
|
||||
«Зачем» отвечает на «зачем нужна эта задача» одним предложением: состояние,
|
||||
остаток, боль. Пересказ первого абзаца бесполезен — он уже есть по ссылке.
|
||||
Эмодзи внутри квадратных скобок не украшение: заголовок копируется **дословно**,
|
||||
и тип виден там, где решают «брать или не брать».
|
||||
|
||||
| Файл | Что отвечает | Секции |
|
||||
| --- | --- | --- |
|
||||
| `ROADMAP.md` | что приложение уже умеет и чего ещё не умеет | канонические и в этом порядке: `Запланировано`, `Направления`, `Сопровождение`, `Готово` (англ. `Planned`, `Directions`, `Operations`, `Done`) |
|
||||
| `BACKLOG.md` | что **можно взять** — только задачи | секции проекта (по умолчанию Ядро/Инфра) |
|
||||
| `BACKLOG.md` | что **можно взять** — только задачи | категории проекта (по умолчанию Ядро/Инфра) |
|
||||
| `SPRINT.md` | какая цель и какой набор под неё | одна: «Набор» |
|
||||
| `REJECTED.md` | что ушло без реализации и почему | — |
|
||||
|
||||
@@ -237,8 +288,15 @@
|
||||
следующем `sprint start` и очищается на `sprint close`.
|
||||
|
||||
Секции — **единственные заголовки `##` в индексе**: любой другой `##` в
|
||||
преамбуле проверка сочтёт секцией. Внутри секции беклога порядок значения не
|
||||
имеет — порядка в беклоге нет вовсе.
|
||||
преамбуле проверка сочтёт секцией.
|
||||
|
||||
**Порядка «по важности» внутри секции беклога нет** — «что делать дальше»
|
||||
отвечает набор спринта. Единственный порядок, который есть, **производен от типа
|
||||
и заполненности**: **сырьё** (`research` без раздела «Вопрос») стоит в конце
|
||||
своей секции, потому что его не берут, и между берущимся оно каждый раз требует
|
||||
открыть файл, чтобы это понять. Проверяет `check`, переставляет `check --fix`,
|
||||
и человек этот порядок не назначает — иначе он был бы приоритетом, которого
|
||||
здесь нет.
|
||||
|
||||
**Секции «блокеры» среди них нет.** Блокер — состояние, а не полка: он живёт до
|
||||
ответа человека, а следы остаются вопросами в файлах задач распущенного спринта.
|
||||
@@ -251,15 +309,14 @@
|
||||
`REJECTED.md`, и по той же причине (файла уже нет, ссылаться некуда).
|
||||
|
||||
**Секции роадмапа закреплены** — состав, полнота, единство языка и **порядок**
|
||||
проверяются `check`; секции беклога проект называет сам. Почему так — SKILL.md.
|
||||
Порядок закреплён потому, что `Готово` копится: стоя первым, достигнутое
|
||||
отодвигает за экран то, ради чего роадмап открывают чаще всего.
|
||||
проверяются `check`; категории беклога проект называет сам. Почему так —
|
||||
SKILL.md. Порядок закреплён потому, что `Готово` копится: стоя первым,
|
||||
достигнутое отодвигает за экран то, ради чего роадмап открывают чаще всего.
|
||||
|
||||
**Заголовок секции пишется с прописной и отбивается пустой строкой с обеих
|
||||
сторон** — во всех индексах, включая секции беклога, имена которых выбирает проект. Написание
|
||||
канонических секций и отбивку правит `check --fix`; он же сводит написание
|
||||
секции в мете файла с заголовком индекса — **имя секции принадлежит заголовку**,
|
||||
файл на неё лишь ссылается, и принадлежность сверяется по нижнему регистру.
|
||||
сторон** — во всех индексах, включая категории беклога, имена которых выбирает
|
||||
проект. Написание канонических секций и отбивку правит `check --fix`; он же
|
||||
сводит написание места в мете файла с заголовком индекса.
|
||||
|
||||
Индексы **производны**: расходятся с файлом — правим индексы (`check --fix`).
|
||||
Строку руками не пишут.
|
||||
@@ -295,19 +352,13 @@
|
||||
|
||||
## Теги
|
||||
|
||||
Единственный механизм разметки, потому что `list --tag` уже умеет отбирать по
|
||||
ним порцию разбора. Отдельных полей меты под это не заводим.
|
||||
Разметка сверх типа. Тип полем, потому что он один и обязателен; теги — потому
|
||||
что их много и `list --tag` уже умеет отбирать по ним порцию разбора.
|
||||
|
||||
- `goal:<слаг>` — цель, которой служит задача. Обязателен **у `kind:feature`**:
|
||||
- `goal:<слаг>` — цель, которой служит задача. Обязателен **у `feature`**:
|
||||
новая возможность и есть содержание цели. У `fix`, `chore` и `research` его
|
||||
может не быть — они служат работоспособности, а не направлению, и в набор
|
||||
спринта входят помимо его цели.
|
||||
- `kind:<род>` — род работы: `feature` | `fix` | `chore` | `research`. Словарь
|
||||
**закрыт**, значение ровно одно. Обязателен у задачи (без него `sprint take`
|
||||
откажет), у цели запрещён, у идеи необязателен. Ставится
|
||||
`add --kind` / `edit --kind`; `--kind` заменяет прежнее значение, а не
|
||||
добавляет второе. Смысл рода и почему он тегом, а не префиксом — в SKILL.md,
|
||||
раздел «Род работы».
|
||||
- `question` — в файле есть неразобранный раздел «Вопросы».
|
||||
- `sprint:<слаг>` — задача заведена в этом спринте; по нему отбирается первая
|
||||
порция разбора («урожай спринта»). **Ставится сам**: слаг спринта заводит
|
||||
@@ -317,6 +368,9 @@
|
||||
разбора — урожай прошедшего спринта».
|
||||
- `decomposed` — на цели: разложена на задачи (см. «Файл цели»).
|
||||
|
||||
Тега `kind:<род>` больше нет: род работы стал типом. Оставшийся в файле `check`
|
||||
называет дрейфом, а `check --fix` снимает, перенеся значение в поле «Тип».
|
||||
|
||||
Отбор — `list --tag a,b`: перечисленные через запятую теги требуются **все
|
||||
сразу** (это И, не ИЛИ). Тег, которого нет ни у одной задачи, `list` называет
|
||||
вслух: молчаливый ноль читается как «таких задач нет», а чаще это опечатка.
|
||||
@@ -327,17 +381,20 @@
|
||||
|
||||
## Тест «готова к взятию»
|
||||
|
||||
Задача готова, если из файла отвечаются четыре вопроса:
|
||||
Задача готова, если из файла отвечаются четыре вопроса. Первый и четвёртый —
|
||||
общие, второй и третий у каждого типа свои и перечислены в его файле.
|
||||
|
||||
1. **Что станет наблюдаемо иначе**, когда она сделана — снаружи: пользователю,
|
||||
владельцу сервиса или разработчику. «Отрефакторить X» — не ответ; «перестанет
|
||||
ломаться Y при Z» — ответ. **У `kind:chore` адресат — разработчик, и это
|
||||
ломаться Y при Z» — ответ. **У `chore` адресат — разработчик, и это
|
||||
законно**: «уедет последний вызов устаревшего API» — ответ, а не отговорка.
|
||||
Род объявлен как раз затем, чтобы такие задачи не выдумывали себе
|
||||
Тип объявлен как раз затем, чтобы такие задачи не выдумывали себе
|
||||
пользовательскую пользу.
|
||||
2. **Каких границ это касается** — раздел «Затрагивает». Без него задачу нельзя
|
||||
оценить: остаётся судить по длине текста.
|
||||
3. **По чему видно, что закончено** — критерии приёмки с оракулами.
|
||||
2. **Что известно про сегодня** — то, что тип требует знать до работы:
|
||||
у `fix` это `Воспроизведение`, у `research` — `Вопрос`, у `feature` и
|
||||
`chore` — `Затрагивает`.
|
||||
3. **По чему видно, что закончено** — критерии приёмки с оракулами;
|
||||
у `research` вместо них `Куда ляжет ответ`.
|
||||
4. **Какую часть «Завершения» своей цели она двигает** — у задачи с целью.
|
||||
Строкой: «двигает пункт 2 «Завершения» — накопительная метрика перестаёт
|
||||
уменьшаться». Это и есть защита от задачи «отрефакторить X»: она проваливает
|
||||
@@ -349,9 +406,10 @@
|
||||
**У задачи без цели** (`fix`, `chore`, `research`) вопрос не задаётся: они
|
||||
служат работоспособности, а не направлению.
|
||||
|
||||
Не отвечается первый, второй или третий вопрос → это **идея** (`[idea]`), её
|
||||
место в штурме. Не отвечается четвёртый у `feature` → либо цель есть и не
|
||||
проставлена, либо это не новая возможность.
|
||||
Не отвечается первый, второй или третий вопрос → это ещё не задача, а **сырьё**:
|
||||
тип `research` без раздела «Вопрос», место — конец секции, работа над ним —
|
||||
штурм. Не отвечается четвёртый у `feature` → либо цель есть и не проставлена,
|
||||
либо это не новая возможность.
|
||||
|
||||
Отвечается всё, но задача не делается одним заходом и не мерджится целиком →
|
||||
это **несколько задач под одной целью**, дроби сразу. Промежуточного зонтика
|
||||
|
||||
Reference in New Issue
Block a user