Проход упрощения уткнулся в один класс у всех пяти агентов: слово, живущее в трёх-шести файлах разом. Правка в одном месте развела бы словарь, правка во всех — уже не упрощение текста скилла. Каждый честно остановился и записал слово в отчёт, и одни и те же слова всплыли в разных отчётах. Разобрано этим проходом. Причина, по которой они вообще накопились, оказалась в самом уставе языка. Он разрешал не переводить «термин, у которого нет точного русского эквивалента и который в команде уже прижился». Проверить это нельзя: прижившимся выглядит любое слово, встреченное трижды, — и ровно так рассудили пять агентов подряд, каждый независимо. Оговорка заменена закрытым списком из девяти терминов с колонкой «что называет»: интейк, триаж, провенанс, дедуп, чек-лист, дифф, промпт, сущности OpenSpec, роды проходов ревью. Интейк оставлен потому, что «заведение» называет создание файла, и слить их значит смешать две операции; провенанс — потому что «источник» рядом называет саму запись, а не свойство числа. Слово не из списка и не из таблицы имён вещей — находка, а не стиль. Список заведён домом язык-словарь в language.md и копией в уставе doc-wording. Копия обязательна: агент работает в репозитории проекта, где плагина может не быть, и без списка предъявил бы интейк как англицизм. Снято пять слов, 29 мест: конфляция → смешение, декорреляция → разведённость, непоймание → почему не поймали, эвал-сет → проверочный набор, гайд → руководство. Латинизм или калька при живом русском слове в каждом случае. Разбор декорреляции показателен: проект уже владел нужным словом — «агенты разведены по глубине», «разведены по охвату» — и держал рядом латинский синоним того же понятия. Это не англицизм, а второй дом для слова. Непоймание снято ещё и потому, что форма журнала дефектов, которую канон кладёт в проекты, спрашивает «Почему не поймали», а проза рядом называла это «причиной непоймания». Скелет и проза о скелете говорили разными словами. Снятое записано вместе с оставленным, в одном списке и с заменой каждого. Иначе слово возвращается: из текстов оно уходит, но ничто не мешает следующему проходу завести его заново — оно ведь короткое и точное на вид. Тема 32 в DECISIONS.md, следствия 124-126. Нумерация правил в уставе doc-wording сдвинута: словарь встал шестым, жаргон и далее уехали на единицу. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
197 lines
16 KiB
Markdown
197 lines
16 KiB
Markdown
# Ведение спринта
|
||
|
||
Спринт — набор задач под одну цель, замороженный до его конца. Здесь то, что
|
||
происходит **внутри** спринта: как задача заканчивается, что считается сделанным,
|
||
кто принимает и что идёт в доклад. Как спринт набирается — шаг 4 в
|
||
[cadence.md](cadence.md).
|
||
|
||
## Наблюдаемые исходы задачи
|
||
|
||
Как они достигаются — дело пайплайна проекта. Сессия знает только исход и его
|
||
след.
|
||
|
||
- **Сделана** — по определению готовности ниже. `close <slug> --implemented`:
|
||
файл и строка удаляются, следом остаётся коммит. **Закрывает агент-оркестратор
|
||
последним шагом пайплайна, после коммита; приёмка человеком идёт позже и
|
||
отменяется `reopen`** — см. «Кто и когда закрывает».
|
||
- **Вышла из спринта** — `sprint drop <slug> --reason …`: возвращается в беклог
|
||
с вопросом в файле и **без живого незакоммиченного предложения** — иначе при
|
||
следующем взятии оно столкнётся с новым. Наработки, которые жалко терять,
|
||
переезжают в тело задачи текстом.
|
||
- **Оказалась крупнее задачи** — распознаётся **до того, как под неё заведено
|
||
предложение об изменении**, иначе его придётся выбрасывать. Выходит из набора,
|
||
уходит на декомпозицию; спринт продолжается остальными, части заводятся под той
|
||
же целью и в замороженный набор не добавляются.
|
||
- **Отменена решением по ходу** — `close <slug> --reason "<ссылка на решение>"`
|
||
прямо из спринта. Это редкий, но законный исход, и он называется в докладе.
|
||
|
||
**Конец спринта** — когда по каждой задаче набора наступил один из исходов. Не
|
||
«все сделаны»: иначе одна застрявшая задача держит спринт бесконечно. Затем
|
||
`sprint close`.
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
take["sprint take — задача в наборе"]
|
||
done["сделана<br/>close --implemented"]
|
||
out["вышла<br/>sprint drop --reason"]
|
||
epic["крупнее задачи<br/>распознаётся до заведения change"]
|
||
cancel["отменена решением по ходу<br/>close --reason"]
|
||
all{"по каждой задаче набора<br/>наступил исход?"}
|
||
harvest["урожай заводится интейком tasks"]
|
||
close["sprint close"]
|
||
dissolve["sprint close --dissolve --reason<br/>недоделанное — в беклог"]
|
||
|
||
take --> done
|
||
take --> out
|
||
take --> epic
|
||
take --> cancel
|
||
done --> all
|
||
out --> all
|
||
epic --> all
|
||
cancel --> all
|
||
all -->|да| harvest
|
||
harvest -->|"тег sprint: ставится, пока SPRINT.md не очищен"| close
|
||
take -->|"продолжать нечем ни одной задачей — блокер"| dissolve
|
||
done -->|"приёмка не сошлась: reopen --reason"| take
|
||
```
|
||
|
||
Два ребра на схеме — те, где порядок обязателен и нарушается молча: **урожай до
|
||
`sprint close`** (после команды автотег уже не поставится) и **блокер в обход
|
||
исходов** (спринт распускается, а не ждёт).
|
||
|
||
Схема — **сводка**: определение готовности и правила приёмки ниже, и при
|
||
расхождении прав текст.
|
||
|
||
**Урожай заводится при закрытии спринта, а не при закрытии задачи.** Это
|
||
обязанность закрывающего: пройти по спискам находок от исполнителей и завести
|
||
недостающее интейком скилла `tasks` — с дедупликацией и картой человеку. Заводимое
|
||
метится тегом спринта само (`sprint:<слаг>`), поэтому первая порция следующей
|
||
сессии поднимается одной командой `list --tag sprint:<слаг>`. Спринт, закрытый
|
||
без этого шага, оставляет находки жить в отчётах — то есть нигде.
|
||
|
||
**Порядок здесь обязателен: урожай заводится ДО команды `sprint close`.**
|
||
Автотег ставится по слагу из `SPRINT.md`, а `sprint close` этот файл очищает;
|
||
заведённое после команды остаётся без тега и в первую порцию следующей сессии
|
||
не попадёт — молча, потому что пустой `list --tag` выглядит как «урожая не
|
||
было». Если так уже вышло, тег ставится руками: `add … --tag sprint:<слаг>`,
|
||
слаг берётся из отчёта `sprint close`.
|
||
|
||
**Провал спринта.** Сработал блокер — спринт распускается (`sprint close
|
||
--dissolve --reason …`), недоделанное возвращается в беклог, новый набор
|
||
делается после ответа человека. Спринт не «ждёт»: ждать может человек, а
|
||
замороженный набор, который нельзя двигать, только мешает.
|
||
|
||
**Протухший набор — второй законный повод роспуска.** Работа стояла, и человек
|
||
вернулся к спринту, состав которого уже не держит в голове. Тем же роспуском:
|
||
`sprint close --dissolve --reason "работа стояла с <когда>"`, недоделанное в
|
||
беклог, новый набор — после переоценки, а не поверх старого.
|
||
|
||
Порога в неделях нет и не будет: счётчик простоя пришлось бы вести руками, а
|
||
решает всё равно человек. Признак — не срок, а **что набор перестал быть твоим**:
|
||
взялся перечитывать, зачем эти задачи вместе, — он протух. Заморозка тут не
|
||
мешает, она запрещает *двигать* набор, а не распустить его целиком.
|
||
|
||
## Определение готовности
|
||
|
||
Задача засчитывается сделанной, когда верно **всё**:
|
||
|
||
1. **Пайплайн задачи пройден до конца** — со своим определением готовности, за
|
||
которое отвечает проект: проверки, состав ревью, документация, коммит. Здесь
|
||
оно не пересказывается и не подменяется — **форма фиксирована, содержание
|
||
даёт `CLAUDE.md` проекта**. Пайплайна нет, задача сделана руками — условие
|
||
читается как «проверки проекта зелёные и изменение влито».
|
||
2. **Критерии приёмки проверены поимённо** — каждый со своим оракулом, исход по
|
||
каждому назван. Это единственное, что добавляет управление задачами: пайплайн
|
||
отвечает «сделано по правилам», критерии — «сделано то, что заказывали».
|
||
3. **Находки по ходу отданы списком** — исполнитель обязан их **назвать**
|
||
(каждую, с пометкой «заведена / не заведена: причина»), но **не обязан
|
||
заводить**: заведение интерактивно — оно требует дедупликации против беклога
|
||
и кладбища, а ещё решений человека. Обязанность **завести урожай** — на
|
||
закрытии спринта, ниже. Иначе автономный исполнитель оказался бы разом и
|
||
обязан завести задачи, и не вправе сделать это в одиночку.
|
||
|
||
### Кто и когда закрывает
|
||
|
||
**Задачу закрывает агент-оркестратор — тот же, кто её и сделал**, последним шагом
|
||
пайплайна, после коммита. Порядок:
|
||
|
||
1. пайплайн доводит задачу до коммита;
|
||
2. **после коммита** зовёт `Skill av-dev-pm:tasks` и закрывает задачу
|
||
(`close <slug> --implemented`); строка уходит из `SPRINT.md`;
|
||
3. **докладывает исход и по каждому критерию — оракул и наблюдаемый исход.**
|
||
Это доклад приёмщику, а не отметка «принято».
|
||
|
||
**Приёмщик и исполнитель здесь совпадают, и это принято сознательно** — цена
|
||
названа в `SKILL.md`, раздел «Стимулы». Поэтому закрытие **не окончательно**, а
|
||
доклад по критериям — не формальность: он единственное, по чему приёмка вообще
|
||
возможна.
|
||
|
||
**Порядок «коммит, потом закрытие» обязателен.** Закрытие удаляет файл задачи;
|
||
упавший коммит после закрытия оставил бы задачу закрытой без единого следа
|
||
работы.
|
||
|
||
**Само закрытие тоже коммитится, отдельным коммитом.** Удаление файла задачи и
|
||
правка индекса — правки в рабочем дереве; пока они не в истории, `SPRINT.md`
|
||
ничего не показывает, а `reopen` восстанавливает текст из `HEAD` в узком окне:
|
||
его закроет первый посторонний коммит. Сообщение про учёт, а не про
|
||
работу: `закрыта задача <slug>`.
|
||
|
||
**Дорога назад существует и обязана быть названа.** Человек на сессии сверил
|
||
критерии, и приёмка не сошлась — `tasks.py reopen <slug> --reason "приёмка не
|
||
сошлась: …"`:
|
||
файл восстанавливается из истории git, строка возвращается в набор идущего
|
||
спринта (или в беклог, если спринта нет), строка кладбища снимается. Тело
|
||
восстанавливается **на момент удаления** — всё, что было дописано позже, живёт
|
||
только в коммите задачи, и это называется в докладе.
|
||
|
||
### Кто и по чему принимает
|
||
|
||
Три условия, без которых пункт про критерии не исполняется никем:
|
||
|
||
1. **Критерии переживают файл задачи.** Файл удаляется при закрытии, поэтому
|
||
критерии копируются туда, где их увидит приёмщик. Куда именно — **отвечает
|
||
пайплайн проекта, а не слот в `CLAUDE.md`**: он переносит их в `tasks.md`
|
||
изменения, когда заводит change. Проект без пайплайна называет своё место
|
||
сам.
|
||
2. **Принимает человек на сессии, а не отдельный агент.** Исполнитель и приёмщик
|
||
в момент закрытия **не разведены** (решение о снятии и его
|
||
цена — в `SKILL.md`, «Стимулы»). Опоры остались три: **сохранённый независимый
|
||
отчёт ревью** (при конвейере `av-dev-pipeline` — отчёт триажа в
|
||
`openspec/changes/archive/<id>/review/`, до архивации — `changes/<id>/review/`),
|
||
`SPRINT.md` под git и `reopen`. Переоценка на сессии и есть момент, когда
|
||
критерии видит не исполнитель. **Конвейера ревью в проекте нет — первой опоры
|
||
нет тоже**, и это называется строкой доклада, а не обходится молча
|
||
(`SKILL.md`, «Стимулы»).
|
||
3. **Расхождение — дефект критериев.** Приёмщик правит критерии и возвращает
|
||
задачу исполнителю **в этом же спринте**: ответ есть, остаток есть, по тесту
|
||
про остаток это не выход из спринта.
|
||
|
||
## Что врывается в замороженный набор
|
||
|
||
Только два класса — правило и его обоснование в SKILL.md. Здесь механика:
|
||
|
||
- вторжение **не добавляет** задачу в набор: `SPRINT.md` остаётся набором под
|
||
цель. Внеплановая работа делается и называется в докладе отдельной строкой
|
||
«внеплановое: что и почему»;
|
||
- если внеплановое требует больше пары часов, честнее распустить спринт, чем
|
||
делать вид, что набор соблюдается;
|
||
- всё остальное падает в беклог через обычный интейк и ждёт сессии.
|
||
|
||
## Доклад в конце спринта
|
||
|
||
Проверяемые якоря, а не пересказ:
|
||
|
||
- **Цель спринта** и по каждой задаче набора: **хеш коммита**, дословный исход
|
||
проверок проекта, **исход по каждому критерию приёмки**.
|
||
- **Какие развилки решались** и чем обоснованы.
|
||
- **Урожай:** сколько задач заведено, какие вопросы накопились, что вышло из
|
||
спринта и почему, что было внеплановым.
|
||
- **Поимённая сверка урожая** с независимыми отчётами ревью: каждая отложенная
|
||
находка имеет либо слаг, либо строку «не заведена: причина». Нулевой урожай при
|
||
непустом отчёте — сигнал, а не благополучие. **Отчётов нет** (проект без
|
||
конвейера ревью) — сверять не с чем, и строка доклада говорит именно это, а не
|
||
«сверено».
|
||
- **Созрела ли порция для сессии.** Решение звать — человека, напоминание —
|
||
обязанность агента: `⌈урожай / 8⌉` порций.
|
||
- **Границы покрытия** сжатой строкой: что в этом спринте не проверялось вовсе.
|