готово | запланировано | направления | разработка, англ. done | planned |
directions | tooling. Из четырёх предложенных имён отвергнуто одно, и по
проверяемой причине: «окружение» уже занято — в architecture.md это боевое
окружение приложения, «где работает, что рядом, кто перезапускает», и одно
слово в двух смыслах развело бы документы канона.
Секции роадмапа стали каноническими, в отличие от секций беклога, и разница
выведена, а не назначена: у каждой секции роадмапа своя семантика, в первую
пишет сам close, и роадмап, названный по-своему, читался бы только своим
автором. Секции беклога — полки, смысла не несут, остаются делом проекта.
check проверяет три вещи: состав закреплён (чужая секция — ошибка), все четыре
обязаны быть, язык один на весь индекс. Проверено на том случае, ради которого
правило и заводилось: «Что уже пройдено», которую healthlog вёл руками, теперь
называется ошибкой поимённо. Оба языка прогнаны вживую, включая close в
английский роадмап.
Ключа tasks.achieved_section не появилось — секция достигнутого опознаётся по
каноническому имени в любом из языков; --roadmap-sections у init упразднён,
выбирать больше нечего.
Названные вслух компромиссы: «готово» слегка тянет в трекерную рамку
«состояние работы», тогда как секция про возможность — перевесила читаемость;
цель в «запланировано» может быть уже наполовину построена, это очередь, а не
«не начато», «в работе» живёт в SPRINT.md.
DECISIONS 19: ГГГ переписан, добавлен ДДД, следствие 78 заменено. TODO 7 закрыт.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Основной инструмент владельца отвечал на половину своего вопроса. Оценка идёт
по поведению: что приложение уже может и чего ещё не может, — а close
--implemented удалял у достигнутой цели и файл, и строку, так что роадмап по
построению показывал только «что осталось». Свидетельство лежало в самом
роадмапе healthlog: секция «Что уже пройдено» на двадцать строк прозы, руками,
с припиской «Эти звенья целями не заведены: закрытая цель записи не оставляет».
Теперь строка с датой переезжает в секцию достигнутого, файл удаляется
по-прежнему. Вторым домом поведения это не делает: нормативное поведение живёт
в openspec/specs, роадмап отвечает, когда и в каком порядке оно появилось.
Ссылки на файл в строке нет — файла больше нет, форма как в REJECTED.md.
Цель стала возможностью приложения, задача — шагом к ней:
- заголовок цели отвечает на «что приложение будет уметь»; свойство поведения
(«сообщает о своём состоянии», «исход не зависит от порядка») — тоже
возможность и переформулировки не требует;
- «Завершение» — списком, а не абзацем: задача ссылается на его строку, и это
новая защита от «отрефакторить X» вместо прежнего «наблюдаемо снаружи».
Заодно видно обратное: строка, к которой не относится ни одна задача, —
незакрытая часть возможности;
- работа над инструментом и процессом на этот вопрос не отвечает и живёт в
отдельной секции.
Цель обязательна не у всякой задачи. Прежнее «иначе она не попадёт ни в один
спринт» было угрозой, а не аргументом, и заставляло операционную работу
выдумывать себе направление. Граница по роду: feature без цели не бывает, fix,
chore и research живут без неё и входят в набор помимо цели спринта.
Тип [epic] упразднён: зонтиком стала цель, а слишком крупный шаг дробится под
ней. Ноль употреблений на 97 записей двух живых проектов.
Секции роадмапа — умеет / строим / направления / станок, четыре вместо двух;
имена приняты как временные и запаркованы (TODO 7). Имя секции достигнутого
знает скрипт — docs/.pm.json, ключ tasks.achieved_section. reopen цели снимает
строку достигнутого, круг проверен вживую.
Всё дописано в версию 3 канона: она ещё нигде не выкачена. DECISIONS 19,
YYY–ГГГ и следствия 78–81.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Полный набор гонялся чаще, чем оправдано, и размер задач тут вторая причина,
не первая. Первая — триггеры: миграция схемы, публичный контракт и инвариант
поднимали ступень, не добавляя ни одного прохода. Миграцию гоняет gate шагом
миграций и разбирает ops, контракт сверяет specs направлением code→spec,
инвариант даёт основание для critical любому проходу — все трое уже в
standard. На проекте с базой и эндпоинтами верхняя ступень оказывалась не
исключением, а умолчанием: правило объявляло исключением то, что происходит
всегда.
Теперь ступень поднимает то, что даёт работу новому проходу. wide означает
ровно одно — изменение вводит новое понятие или структурную единицу; добавить
поле в существующий ответ это не концепт. standard стал рабочим умолчанием.
Проект, где изменение контракта и правда архитектурное, поднимает его сам в
docs/review.md — уточнением, а не возвратом прежнего умолчания.
Чекпоинт design получил то же условие: specs идёт всегда, rubric и
architecture — только при новом понятии. Он стоит на каждой задаче, поэтому
при мелкой нарезке три прохода умножаются на число задач.
Со стороны задач — шов нарезки: тест декомпозиции отвечает, допустим ли
разрез, шов отвечает, где его провести. Резать по границе, за которой падает
ступень; не резать, когда обе половины остаются в одной — костяк из четырёх
проходов платится за каждую задачу, и такой разрез делает ревью дороже.
Порога в числе границ нет по тому же принципу, что в теме 16: размер не
триггер. Дешёвое место заметить разнородную задачу — показ набора спринта,
там «Затрагивает» уже написан, а предложение ещё не заведено.
Правило выведено из состава проходов, а не из статистики прогонов — замер
остаётся за обкаткой. DECISIONS 18, RRR–WWW и следствия 72–75; JJJ темы 17
помечен как пересмотренный. Шаг про «Триггеры профиля» дописан в ещё не
выкаченную версию 3 канона, а не отдельной версией.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Три изменения одной версией, потому что все три про одно — можно ли
оценить задачу, не открывая код.
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>
Поля Дата и Источник приведены к общей форме меты (поле на строку, имя
жирным) — той же, что у задачи и у записи журнала дефектов.
Существеннее второе. Правило «передумали — новая запись, старая получает
статус» жило в каноне с первой версии, но места под статус шаблон не отводил:
каждая запись изобретала своё — то абзацем, то заголовком, — а колонка
«Статус» таблицы adr/README.md обязана его показывать и брала оттуда, где он
у каждого свой. Теперь статус — такое же поле шапки, у активной записи его
нет.
Правка ушла в дом (canon.md, раздел adr/) и в оба скелета: template.md и
«Соглашения» в adr/README.md. Скелеты уезжают в репозиторий проекта, поэтому
версия канона поднята до 2 с записью в changelog: что добавилось, что
переехало и три шага проекту. Копии под маркерами не тронуты — copies.py
дословность подтверждает.
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-git ни от чего не зависит.
av-dev-pipeline проходим на задаче, заданной одной строкой текста, — кроме одного
места. Третья цель в исходной формулировке недостижима, и поправлена формулировка,
а не картина.
av-dev-pm владеет docs/review.md — конфигурационным файлом конвейера с «Вопросами
к проходам» и «Триггерами профиля», то есть знает проходы поимённо по построению.
Кто-то этим словарём владеть обязан. Честная формулировка: pm не зовёт пайплайн и
не требует его наличия — и она выполняется.
Настоящая протечка была одна: опоры приёмки в «Стимулах» и sprint.md держались на
отчёте триажа по конкретному OpenSpec-пути. В проекте без конвейера защита от
занижения урожая исчезала молча. Теперь опора названа абстрактно, путь дан частным
случаем, отсутствие конвейера обязано попадать строкой в доклад спринта.
Ветка деградации шага 9 была неисполнима ровно в том случае, ради которого
написана: «плагина нет — открой av-dev-pm/skills/canon/references/canon.md», путь в
дерево маркетплейса. Пайплайн теперь ходит в свой project-facts.md, а ссылки в
чужой плагин даются через Skill.
Две симметричные копии уже разошлись: форма журнала дефектов (шесть полей против
пяти, «Причина» потеряна) и читатели docs/research/ («specs» выпал). Дома
назначены, копии помечены, обязанность тянуть запись в журнал версий записана.
Плюс: пайплайн не называет items/ и SPRINT.md — их имена проект вправе сменить;
манифесты объявили av-dev-pm опциональным и приём задачи текстом.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- sprint.md прямо запрещал шаг, который пайплайн теперь делает: раздел «кто и
когда закрывает» переписан под снятую границу приёмки
- закрытие задачи стало шагом 11, после коммита: раньше упавший коммит оставил
бы задачу закрытой без следа работы
- контракт close --implemented больше не обещает состоявшуюся приёмку
- слот «куда копируются критерии приёмки» убран из session: на него отвечает
пайплайн, а канон его не заводил
- research/ в таблице ролей вернул adversary; журнал версий поднимает CLAUDE.md
целиком, а не тремя пунктами из восьми
- TODO и REMAINING перестали занижать: коммитов одиннадцать, переписок три
- av-dev-tasks → av-dev-pm; канон определён единственным reference-файлом,
который читают все три новых скилла
- canon: check/adopt/upgrade плюс docs.py — раскладка, битые ссылки, версия,
маркеры долга, сверки миграций и capability с документацией
- tasks и session: путь docs/tasks жёсткий, конфиг переехал в docs/.pm.json,
слот «Команда учёта задач» убран в пользу вызова скилла, раздел «Стимулы»
переписан под совпавших приёмщика и исполнителя