Files
dev-skills/av-dev-pm/skills/session/references/sprint.md
T
avandClaude Opus 5 cbfae90f3f словарь: пять слов сняты, девять закрыты списком вместо оговорки «прижилось»
Проход упрощения уткнулся в один класс у всех пяти агентов: слово, живущее в
трёх-шести файлах разом. Правка в одном месте развела бы словарь, правка во
всех — уже не упрощение текста скилла. Каждый честно остановился и записал слово
в отчёт, и одни и те же слова всплыли в разных отчётах. Разобрано этим проходом.

Причина, по которой они вообще накопились, оказалась в самом уставе языка. Он
разрешал не переводить «термин, у которого нет точного русского эквивалента и
который в команде уже прижился». Проверить это нельзя: прижившимся выглядит
любое слово, встреченное трижды, — и ровно так рассудили пять агентов подряд,
каждый независимо. Оговорка заменена закрытым списком из девяти терминов с
колонкой «что называет»: интейк, триаж, провенанс, дедуп, чек-лист, дифф,
промпт, сущности OpenSpec, роды проходов ревью. Интейк оставлен потому, что
«заведение» называет создание файла, и слить их значит смешать две операции;
провенанс — потому что «источник» рядом называет саму запись, а не свойство
числа. Слово не из списка и не из таблицы имён вещей — находка, а не стиль.

Список заведён домом язык-словарь в language.md и копией в уставе doc-wording.
Копия обязательна: агент работает в репозитории проекта, где плагина может не
быть, и без списка предъявил бы интейк как англицизм.

Снято пять слов, 29 мест: конфляция → смешение, декорреляция → разведённость,
непоймание → почему не поймали, эвал-сет → проверочный набор, гайд →
руководство. Латинизм или калька при живом русском слове в каждом случае.

Разбор декорреляции показателен: проект уже владел нужным словом — «агенты
разведены по глубине», «разведены по охвату» — и держал рядом латинский синоним
того же понятия. Это не англицизм, а второй дом для слова.

Непоймание снято ещё и потому, что форма журнала дефектов, которую канон кладёт
в проекты, спрашивает «Почему не поймали», а проза рядом называла это «причиной
непоймания». Скелет и проза о скелете говорили разными словами.

Снятое записано вместе с оставленным, в одном списке и с заменой каждого. Иначе
слово возвращается: из текстов оно уходит, но ничто не мешает следующему проходу
завести его заново — оно ведь короткое и точное на вид.

Тема 32 в DECISIONS.md, следствия 124-126. Нумерация правил в уставе doc-wording
сдвинута: словарь встал шестым, жаргон и далее уехали на единицу.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 15:35:06 +03:00

16 KiB
Raw Blame History

Ведение спринта

Спринт — набор задач под одну цель, замороженный до его конца. Здесь то, что происходит внутри спринта: как задача заканчивается, что считается сделанным, кто принимает и что идёт в доклад. Как спринт набирается — шаг 4 в cadence.md.

Наблюдаемые исходы задачи

Как они достигаются — дело пайплайна проекта. Сессия знает только исход и его след.

  • Сделана — по определению готовности ниже. close <slug> --implemented: файл и строка удаляются, следом остаётся коммит. Закрывает агент-оркестратор последним шагом пайплайна, после коммита; приёмка человеком идёт позже и отменяется reopen — см. «Кто и когда закрывает».
  • Вышла из спринтаsprint drop <slug> --reason …: возвращается в беклог с вопросом в файле и без живого незакоммиченного предложения — иначе при следующем взятии оно столкнётся с новым. Наработки, которые жалко терять, переезжают в тело задачи текстом.
  • Оказалась крупнее задачи — распознаётся до того, как под неё заведено предложение об изменении, иначе его придётся выбрасывать. Выходит из набора, уходит на декомпозицию; спринт продолжается остальными, части заводятся под той же целью и в замороженный набор не добавляются.
  • Отменена решением по ходуclose <slug> --reason "<ссылка на решение>" прямо из спринта. Это редкий, но законный исход, и он называется в докладе.

Конец спринта — когда по каждой задаче набора наступил один из исходов. Не «все сделаны»: иначе одна застрявшая задача держит спринт бесконечно. Затем sprint close.

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⌉ порций.
  • Границы покрытия сжатой строкой: что в этом спринте не проверялось вовсе.