Три изменения одной версией, потому что все три про одно — можно ли
оценить задачу, не открывая код.
PLAN.md → ROADMAP.md. Слово «план» значило в репозитории три разных вещи:
оглавление целей, план реализации внутри задачи и PLAN.json разовой
адаптации. Переименовано целиком — ключ конфига tasks.plan → tasks.roadmap,
--index roadmap, --roadmap-sections, --roadmap. Старый ключ в docs/.pm.json
не игнорируется молча: скрипт останавливается кодом 3 и называет
переименование, иначе проект искал бы опечатку там, где на самом деле
версия канона.
Род работы — тег kind:feature|fix|chore|research, вторая ось поверх типа
записи. В один префикс их не свести: идея бывает про функцию, эпик функцией
и является. Дом — тег, потому что теги здесь единственный механизм
разметки, а list --kind работает даром; цена принята — в строку индекса род
не попадает. Словарь закрыт, иначе он разъедется на bug/bugfix/fix/defect.
Отдельно легализован chore: у него «что станет наблюдаемо иначе» отвечается
разработчику, а раньше такие задачи либо не заводились, либо придумывали
себе пользовательскую пользу — и это второе хуже, оно проходит проверку.
Раздел «Затрагивает» — границы, которых изменение касается: эндпоинт,
таблица и миграция, формат на диске, публичный тип пакета. Без него задача
оценивается по объёму текста, а не по объёму поверхности. Механизируется
только наличие непустого раздела: полноту перечня машина не видит.
Род и границы требуются к взятию в спринт, а не к заведению — тот же приём,
что уже работает для критериев приёмки, и по той же причине. check о
пропаже только напоминает: иначе два живых проекта покраснели бы на 98
задачах, заведённых до этого решения.
Плюс правила языка задач: англицизм, у которого есть русское слово,
заменяется; термин не из паспорта, архитектуры или конвенций вводится
строкой или не употребляется; задача, которую не удаётся сказать просто,
чаще всего не одна задача.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Строкой через · мета уезжала за экран уже на трёх полях, а сам разделитель
приходилось запрещать в тексте причины и «зачем». Списком поле занимает свою
строку, запрещать нечего, и проверка длины схлопнулась до одной строки.
«Хук» переименован в «Зачем» — поле отвечает на вопрос «зачем нужна эта
задача». Слово «цель» под это не годится: оно уже занято [goal]-файлами и
тегом goal:<слаг>, и в одном блоке значило бы две разные вещи.
Хирург мета-строки — самая мутная функция скрипта, резавшая строку на куски с
запоминанием пробелов каждого, — заменён на «прочитать поля и собрать блок
заново». Тем же ходом старая форма переезжает в новую: check называет её
дрейфом, check --fix переписывает списком, Хук становится Зачем. Чужие
нераспознанные поля пересборку переживают.
Проверено на восьми сценариях: add, edit, move с причиной, sprint take/drop,
close --reason + reopen (мета собирается из текста, поднятого из git),
миграция старой формы вместе с чужим полем, отказ на мете без секции.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Метафора требовала расшифровки при каждом употреблении, и в текстах она и
расшифровывалась: «звено упорядоченной линии продукта», «тематический куст —
цель, в последовательность не встающая». Если название приходится объяснять
рядом с каждым употреблением, объясняет не название.
Новые имена называют ровно то свойство, которым секции различаются: в первой
очередь значима и обоснована прозой, во второй порядка нет вовсе.
Заголовки строчные, как ядро/инфра в беклоге: имя секции одновременно значение
для --section, и проза приведена к тому же виду, чтобы «--section Порядок» не
выглядело правильным написанием.
Версия канона не меняется: canon.md называет файл PLAN.md и о его секциях не
говорит — их дом заголовки ## индекса, умолчание живёт в tasks.py.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Два независимых сабагента на av-dev-pm и av-dev-pipeline. Две находки нашли оба.
Главная — моя же перестановка закрытия за коммит сломала reopen и батч. close
печатал «дорога назад из git», а reopen искал коммит удаления, которого в новом
порядке ещё нет: шаг 11 последний, учёт остаётся незакоммиченным. Проверено
прогоном — отказ кодом 2 на свежезакрытой задаче. Тем же грязным деревом
ломались rebase и worktree remove в батче: каждая закрывшая задачу ветка уехала
бы в провалившиеся.
Починено с обеих сторон: reopen берёт текст из HEAD, если коммита удаления нет,
а шаг 11 коммитит учёт вторым коммитом.
Вторая — канонический пример docs/.pm.json убивал tasks.py. Четыре документа
показывали ключ tasks.sections, которого скрипт не знает: неизвестный ключ это
код 3 на любой команде. Проект, заведённый по канону дословно, остался бы без
работы с задачами, а docs.py при этом печатал «канон соблюдён». Секции живут в
заголовках индекса и второго дома не получают.
Остальные восемнадцать: init писал конфиг в упразднённый .tasks.json;
looks_like_tasks не видел переименованный индекс; урожай спринта терял автотег
после sprint close; ответ на вопрос по инструкции оставлял задачу незабираемой;
adopt требовал недостижимого зелёного; путь отчёта триажа не переживал archive;
review-specs не имел режима для стыка после слияния; три остатка «шаг 9а» несли
предкоммитную позицию закрытия; sprint.md отрицал сам себя в пункте «Сделана».
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- av-dev-tasks → av-dev-pm; канон определён единственным reference-файлом,
который читают все три новых скилла
- canon: check/adopt/upgrade плюс docs.py — раскладка, битые ссылки, версия,
маркеры долга, сверки миграций и capability с документацией
- tasks и session: путь docs/tasks жёсткий, конфиг переехал в docs/.pm.json,
слот «Команда учёта задач» убран в пользу вызова скилла, раздел «Стимулы»
переписан под совпавших приёмщика и исполнителя