Проход упрощения уткнулся в один класс у всех пяти агентов: слово, живущее в
трёх-шести файлах разом. Правка в одном месте развела бы словарь, правка во
всех — уже не упрощение текста скилла. Каждый честно остановился и записал слово
в отчёт, и одни и те же слова всплыли в разных отчётах. Разобрано этим проходом.
Причина, по которой они вообще накопились, оказалась в самом уставе языка. Он
разрешал не переводить «термин, у которого нет точного русского эквивалента и
который в команде уже прижился». Проверить это нельзя: прижившимся выглядит
любое слово, встреченное трижды, — и ровно так рассудили пять агентов подряд,
каждый независимо. Оговорка заменена закрытым списком из девяти терминов с
колонкой «что называет»: интейк, триаж, провенанс, дедуп, чек-лист, дифф,
промпт, сущности OpenSpec, роды проходов ревью. Интейк оставлен потому, что
«заведение» называет создание файла, и слить их значит смешать две операции;
провенанс — потому что «источник» рядом называет саму запись, а не свойство
числа. Слово не из списка и не из таблицы имён вещей — находка, а не стиль.
Список заведён домом язык-словарь в language.md и копией в уставе doc-wording.
Копия обязательна: агент работает в репозитории проекта, где плагина может не
быть, и без списка предъявил бы интейк как англицизм.
Снято пять слов, 29 мест: конфляция → смешение, декорреляция → разведённость,
непоймание → почему не поймали, эвал-сет → проверочный набор, гайд →
руководство. Латинизм или калька при живом русском слове в каждом случае.
Разбор декорреляции показателен: проект уже владел нужным словом — «агенты
разведены по глубине», «разведены по охвату» — и держал рядом латинский синоним
того же понятия. Это не англицизм, а второй дом для слова.
Непоймание снято ещё и потому, что форма журнала дефектов, которую канон кладёт
в проекты, спрашивает «Почему не поймали», а проза рядом называла это «причиной
непоймания». Скелет и проза о скелете говорили разными словами.
Снятое записано вместе с оставленным, в одном списке и с заменой каждого. Иначе
слово возвращается: из текстов оно уходит, но ничто не мешает следующему проходу
завести его заново — оно ведь короткое и точное на вид.
Тема 32 в DECISIONS.md, следствия 124-126. Нумерация правил в уставе doc-wording
сдвинута: словарь встал шестым, жаргон и далее уехали на единицу.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Эксперимент: по сабагенту на каждый скилл av-dev-pm, задача — переписать текст
более простыми словами, но только там, где уверен и без потери смысла и
точности. Нормой служил устав языка самого проекта, language.md, включая его
раздел «Порог правки»: правка без нарушенного правила не делается.
36 правок в двенадцати файлах, +64/-63 — почти строго замена, а не
переписывание. Правили залог (пассив с названным деятелем в творительном),
отглагольные существительные, параллельность перечней, канцелярит «является»,
пару garden-path и одно двойное отрицание. Контракт не задет нигде: в диффе нет
изменённых строк-заголовков, а код-спаны встречаются ровно парой минус-плюс,
то есть ни имя, ни флаг, ни путь не переписаны.
Отчёты «что рассматривал и не тронул» вышли длиннее отчётов о правках у всех
пятерых, и это главный результат прогона. Самый частый повод остановиться —
слово, живущее в четырёх файлах: конфляция, интейк, провенанс, непоймание.
Правка в одном месте развела бы словарь, а править все — уже не упрощение
текста скилла, а сквозной проход по репозиторию. Второй повод — формулировка,
дословно повторённая в соседнем плагине: декорреляция, материализация
нерешённого, «при расхождении прав текст».
Шестой агент проверил все 36 правок и нашёл четыре.
Перестановка слов в task-research.md развела формулу с её домом: «число без
источника проход ревью обязан читать как условие» стоит в canon.md и в уставе
doc-consistency, который прямо ссылается на канон как на источник. Откачено —
это ровно тот класс расхождения, который сам doc-consistency и ловит.
«Держит H1, мету и индекс в согласии» — управление требует дополнения, а
language.md в разделе англицизмов прямо оговаривает: русский аналог звучит
коряво — остаётся термин. Взят третий вариант, «согласованными».
В skeletons.md «правка тянет запись, и она называет» — местоимение указывает
на два женских существительных сразу. Стало «и запись называет».
Четвёртая находка не откачена: правка в init/SKILL.md хорошая, но развела
конструкцию с близнецом в canon/SKILL.md — выровнена вторая половина.
Побочно найдена старая логическая инверсия в DECISIONS.md, решение U:
«становится неотличимым, только если отрицание обязательно» — смысл вывернут,
в docs/SKILL.md и во второй записи журнала он правильный. Починено.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Сабагент в роли продакт-менеджера оценил покрытие жизненного цикла личного
проекта скиллами и агентами av-dev-pm. Скоуп сужен по ходу разбора: деплой и
разбор инцидентов делаются вручную, скиллов под них не заводим — три находки
из восьми сняты этим сразу.
Шаг 2 сессии требовал чисел, которых процесс отказался собирать решением.
cadence.md делал обязанностью пересмотр «ориентира по размеру спринта, прироста
беклога на закрытую задачу, времени на задачу» и «сколько заняли задачи против
ожидания». Данных нет: у записи нет дат заведения, взятия и закрытия, close
удаляет файл, sprint close очищает SPRINT.md. Хуже, «против ожидания» и «время
на задачу» требуют оценки и тайм-бокса, а session/SKILL.md в «Почему не Scrum»
их прямо не берёт — пункт противоречил решению через файл от себя. Числа не
пересматривались ни разу, поэтому выкинуты, а не подперты учётом дат. Осталось
качественное; рядом записано, что замеров нет намеренно, иначе следующий
читатель заведёт их обратно как недостающие. Шаг 3 пункт 9 переименован из
«переоценки по измеренному» в «по пройденному».
doc-consistency переехал с каждого синка на сессию, к doc-code-drift. Агент на
opus звался шагом 9 пайплайна, то есть 5-8 opus-проходов за спринт по документам,
меняющимся на несколько абзацев. Довод сильнее денег: расхождение между двумя
документами по определению требует двух, а на большинстве задач синк правит
один. И пачка, отбираемая работой, не видит того, чего работа не касалась, —
а расхождение живёт ровно там. Это снимает открытый вопрос REMAINING про охват
парного статуса ADR. Цена — потеря привязки находки к задаче, принято сознательно.
Отмена цели получила порядок, но не флаг. close запрещал закрыть цель с живыми
задачами и не говорил, что с ними делать. Теперь: сперва задачи поштучно
(close --reason своей причиной либо edit --goal на другую), потом цель в
REJECTED.md, а не в Готово. Флаг --cascade отвергнут: поштучный разбор — не
церемония, а единственный момент, когда видно, что переживёт цель. Место
процедуры — переоценка на сессии, отмена цели и есть разбор её задач.
У брошенного спринта появился второй законный исход. --dissolve везде был
привязан к блокеру, и вернувшийся к месячному набору не имел законного хода:
двигать нельзя, распускать не по чему. Теперь роспуск объясняется блокером или
тем, что набор протух. Порога в неделях нет — тот же класс, что выкинутые
числа: счётчик простоя пришлось бы вести руками. Признак не срок, а что набор
перестал быть твоим. Плюс точка входа «вернулся, а спринт открыт» и триггер в
description скилла.
Журнал канона прогоняется как есть, схлопывать 3 и 4 не стали. Взамен появилась
проверка исхода: шагом 6 adopt и шагом 6 upgrade зовутся оба судьи документов.
Это ответ на открытый вопрос «как проверять, что канон не разошёлся с проектами
после upgrade»: check сверяет число в .pm.json с версией скрипта и про существо
записи не знает ничего, а записи применяются руками.
Износ обязательных «границ покрытия» не правится: это гипотеза, а не находка.
Записана наблюдением к первой обкатке. Предложение агента поднять обкатку выше
калибровки снято — TODO уже так устроен, агент спутал «главный риск» с «первое
в очереди»; в REMAINING добавлена оговорка против того же прочтения.
Тема 31 в DECISIONS.md, следствия 117-123.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Плагин был помечен устаревшим решением Q и жил до перевода jellybit.
Удалён раньше этого срока: условие пережило свою причину.
Заморозка выглядела бесплатной, а платила собой в каждой проверке
репозитория — exclude в pyproject.toml, SKIP_DIRS в copies.py, два абзаца
README, оговорка в описании маркетплейса, чтобы не ловить триггер
«добавь задачу в беклог». Пять исключений ради 706 строк, которые никто
не читает, и каждое надо объяснять всякий раз, когда спрашивают, почему
проверка обходит каталог.
Причина условия отпала раньше названного срока. docs/backlog/ читает не
backlog.py, а av-dev-pm:tasks — adopt.md и адаптер в tasks.py держат ту
же раскладку как вход миграции. Плагин перестал быть единственным, кто
её знает, ещё когда писался adopt, и «живёт до перевода последнего
проекта» с тех пор охраняло пустоту. Перевод jellybit на канон это не
задевает.
Порядок вышел обратный ожидаемому: плагин удалён из маркетплейса, а с
jellybit снят после. Ожидалась ручная чистка enabledPlugins и
installed_plugins.json, но claude plugin uninstall отработал штатно — он
идёт по реестру, а не по манифесту маркетплейса. Раздел «Снятие» в README
переписан с частного случая на общую процедуру, предупреждение заменено
проверенным фактом.
Записи Q и HH получили парные статусы, тема 30 в DECISIONS несёт причины
и три следствия, пункт 5 TODO отмечен, открытый вопрос из REMAINING убран.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Первый прогон агента — по репозиторию, который его же и содержит. Два
прохода, 17 находок, все подтверждены по файлам.
Пять находок — остатки прежней модели типов в файлах, до которых я не
дошёл двумя коммитами раньше. adopt.md держал имена секций роадмапа
канона 2 («порядка», «темы») и «пустой goal законен только у идеи»;
from-review.md и TODO.md — упразднённый [idea]; task-batch в другом
плагине — «задачи-идеи». Правку модели я вёл от документов, которые
менял, а не от тех, что на них ссылаются: grep по упразднённому слову
дал бы все пять за минуту.
Самая дорогая находка оказалась моей и свежей. Таблица типов в canon.md
объявляла цель у fix запрещённой, а tasks/SKILL.md и task-fix.md —
необязательной; код на стороне вторых. Копия разошлась с домом за один
день, обе половины писал один проход. Поправлено не значение, а причина:
canon.md дважды объявлял, что фиксирует только словарь типов, — значит
колонкам «разделы» и «цель» в нём не место. Осталась таблица из двух
колонок и ссылка на дом схемы.
Перечень «чем держат проект» пересказывался втроём и разъехался:
«метрики и логи» против «мониторинга», «проверки» есть в двух из трёх.
При этом tasks/SKILL.md ссылался на дом рядом с собственным пересказом —
ссылка не мешает копии разойтись, если копия всё равно стоит. Перечень
остался в canon.md, два места ссылаются.
README пересказывал раскладку канона блоком кода, и копия была уже
неполна — не хватало путей, чьё отсутствие docs.py считает нарушением.
Заменено ссылкой. Там же измеренное число из DECISIONS III заменено
ссылкой на решение.
REMAINING дублировал два отмеченных сделанными пункта TODO и держал
счётчики, которые обязан двигать человек: «двенадцати тем и 16 коммитов»
(стало 28 и 52), «три неизмеренных изменения» (стало больше). Счётчики
отменены как класс, причина записана в шапку. Открытый вопрос про парный
статус ADR переформулирован: судья появился, открыт остался охват.
Три противоречия вне av-dev-pm: --roadmap-sections перечислен среди
флагов init прозой того же файла, объявляющей, что его нет; review-ops
берёт журнал docs/review.md и тут же объявляет историю инцидентов
принципиально недоступной; «честный предел» конвейера отменял целиком
документ docs/research/. Плюс битый якорь ссылки на раздел вычитки.
Находка про Co-Authored-By снята как неверная: агент прочитал
av-dev-git/skills/commit/SKILL.md как описание практики этого
репозитория, а это продукт, уезжающий в чужие проекты. Устав агента не
различает «документ про нас» и «документ про то, что мы производим» —
остаток записан в REMAINING, в устав пока не дописан.
DECISIONS тема 29 (ЧЧШШ–ЮЮЯЯ, следствия 109–113).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Оба пункта заметок оказались одним классом: правило записано и никем не
исполняется.
Слаги. canon.md говорил «слаги файлов, capability и задач — английские,
kebab-case» одной строкой в хвосте раскладки, а docs.py имён файлов не
смотрел вовсе. Итог нашёлся в самом плагине: единственный пример ADR в
скилле docs назывался ADR-2026-08-03-ochered-tablicej. Раскладка канона
при этом приглашала к нарушению — в схеме стояли плейсхолдеры <тема>.md,
то есть слово «тема» по-русски там, где надо писать <slug>.
docs.py check теперь смотрит имена: кириллица и не-kebab-case жёстко,
форма ADR-ГГГГ-ММ-ДД-slug.md жёстко, транслит эвристикой, то есть
замечанием. Проверяются docs/conventions, docs/research, docs/adr и имена
capability; каталог задач не трогается — его слаги ведёт tasks.py.
Набор маркеров транслита подобран так, чтобы ложных срабатываний не было
вовсе: выброшены ost (ловит post, cost), sch (schema), ya (yaml), nost
(nostalgia), хвост ii (radii). Цена названа в комментарии —
sostoyanie-partii проходит мимо. Правило, краснеющее на правде, приучает
пролистывать весь блок, и это дороже пропуска.
Агенты. В canon.md есть таблица «Что проверяет машина, а что человек», и
её правая колонка — смысловой дубль, поведение в architecture.md,
протухший факт, достаточность честной строки — три версии описывала
работу, которую никто не делал: скилл canon предлагал агенту судить об
этом самому, то есть проверять то, что он же и писал.
Заведены двое, разрез по глубине — тот же довод, что развёл task-form и
doc-wording. doc-consistency читает docs/ и openspec/, сверяет документы
между собой (факт в двух домах, прямое противоречие, поведение в обзоре
вместо спек, ADR без ссылки на design.md и без парного статуса, число без
провенанса, заглушка вместо честной строки) и зовётся на шаге синка
документации. doc-code-drift читает репозиторий, отвечает на «этот факт
ещё верен» и зовётся раз в спринт на сессии.
Перечень фактов, сверяемых с кодом, закрыт: имя ветки, команды, пути,
зависимости поимённо, настройки с числом, единые точки проекта,
capability, проверяемые инварианты. «Сверить архитектуру с кодом» —
задача без дна, и агент, которому её поставили, выдаёт правдоподобную
труху. Отсюда форма его доклада: начинается таблицей проверенного, а не
находками, — по ней видно, чего он не смотрел.
Карта домов уехала в устав doc-consistency помеченной копией: устав
ссылался на файл плагина, а агент работает в репозитории проекта, где
плагина может не быть. copies.py её сторожит.
Попутно: докстрока copies.py показывала закрывающие маркеры как
<!-- /дом -->, а код требует <!-- /дом: <id> -->. Нашлось первой же
попыткой ими воспользоваться.
DECISIONS тема 28 (ННОО–ХХЦЦ, следствия 105–108).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Осей было две — тип записи (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>
healthlog уже переехал на канон 3, а переименование секции я внёс
правкой записи версии 3 задним числом — то есть переписал текст, по
которому он ехал. Посылка «ни один проект на каноне 3 не стоит» была
ложной, решение ШШШ отменено.
Запись версии — черновик ровно до первого переехавшего проекта. После
этого она история, и любое изменение канона заводит новую версию, даже
если меняется одно слово. Проверять дёшево: grep '"canon"' по живым
проектам. Дорого обратное — проект, повышенный по тексту, которого
больше не существует, невоспроизводим.
Запись версии 3 восстановлена дословно (Разработка | Tooling),
переименование уехало в версию 4. jellybit, стоящий на каноне 2,
прочтёт обе записи подряд и заведёт Разработка, чтобы через шаг
переименовать; в шаг версии 3 добавлена оговорка «едешь сразу на 4 —
заводи Готово последней и не переставляй дважды».
«Готово» переехало вниз, и порядок секций стал каноническим.
Достигнутое копится: через год этой секции больше, чем всех остальных
вместе, и стоя первой она отодвигает за экран то, ради чего роадмап
открывают чаще всего. Порядок проверяет roadmap_lint, переставляет
check --fix — вместе с содержимым секций, потому что двигать десяток
строк руками это работа, на которой ошибаются. Чужую секцию
перестановка не трогает вовсе: её место в порядке неизвестно.
Индексы позиций считаются из самого кортежа: ACHIEVED был 0 и стал 3,
хардкод пережил бы перестановку молча и сломал бы close.
Обкатка нашла два дефекта оформления, оба порождённые самой
перестановкой. Отбивка нужна и перед заголовком — сдвиг блоков ставит
два заголовка вплотную. Удаление строки индекса оставляет две пустые
подряд, и пустоты копятся. Проверка оформления теперь сверяется с самим
нормализатором, а не своим набором условий: два описания одного правила
разъедутся, и check начнёт молчать о том, что --fix правит.
CANON_VERSION = 4 в docs.py, примеры .pm.json в canon.md и skeletons.md.
DECISIONS тема 26 (ЭЭЭ, ЮЮЮ, ЯЯЯ, следствия 98–100).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
«Разработка» называла слишком много: роадмап весь про разработку, и
секция с таким именем не отличалась от остальных ничем. Стало
Сопровождение | Operations.
Смысл расширен вместе с именем: было «инструмент и процесс», стало «чем
держат проект: инструмент, процесс, эксплуатация». Расширение не
косметическое — английское Operations при узком смысле обещало бы
эксплуатацию, а внутри лежал бы линтер. Метрики, логи, инфраструктура и
выкладка в эту секцию просятся и так.
Заодно синхронизирован словарь трёх мест канона, которые про одну тему.
Сопровождение — всё, чем держат проект; эксплуатация — его часть, работа
системы на проде. ROADMAP.md, секция Сопровождение — план работ;
architecture.md, раздел «Эксплуатация» — как устроено сейчас;
эксплуатационный проход ревью — оптика проверки. Сливать их в одно слово
было бы ошибкой: они отвечают на разные вопросы. Синхронизирован
словарь, а не границы; дом — canon.md. Слово «поддержка» запрещено
вовсе: в нём слышится помощь пользователю.
Граница с возможностями проходит по тому, кто наблюдает: «приложение
сообщает о своём состоянии» — возможность, «дежурный видит состояние на
одном экране» — сопровождение.
Версия канона не менялась, и это законно: ни один проект на каноне 3 не
стоит, оба держат канон 2. Запись версии 3 правится как черновик, а не
как история — версия отделяет одно состояние проектов от другого, а не
одну редакцию текста от другой.
DECISIONS тема 25 (ЧЧЧ, ШШШ, ЩЩЩ, следствия 96–97).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Обкатка обоих проходов на тестовом наборе нашла два расхождения в
правилах, которые я же и написал.
«Одна мысль — одно предложение» не распространяется на поля меты.
doc-wording предложил разбить «зачем» надвое, а task-format.md требует
от него одного предложения: оно повторяется строкой индекса, и второму
там не поместиться. Агент честно выполнил тот документ, который читал;
виновато правило без оговорки. Оговорка записана и в доме language.md, и
в уставе: тесно — сокращай, но не дели.
«Не своё» бывает двух родов. Чужому подрядчику — строкой в границах
покрытия, чтобы находка не пропала. Машинной проверке — вообще ничего,
даже строкой: это не потерянная находка, а уже проверенное. doc-wording
отправил в «замечено не по моей части» открытый вопрос в задаче, который
ловит tasks.py check, и строка получилась шумом, выглядящим как работа.
Разделение прописано в обоих уставах.
DECISIONS тема 24 (ХХХ, ЦЦЦ, следствия 94–95).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
В уставе стоял заголовок «Форма записи — только для docs/tasks/items/»:
условная половина, которая на документе канона молчит, а на задаче
включается. Условное правило агент применяет по своему усмотрению, а
усмотрение и есть то, чего от него не ждут. Два коротких устава без
условий надёжнее одного длинного с ними.
Разделены не по охвату — по глубине. Язык проверяется по словам и
фразам, поштучно: залог, оценки, стоп-слова, англицизмы, жаргон. Форма
записи требует понять, что задача делает, и открыть файл цели, на
которую она ссылается, чтобы сверить, какую строку «Завершения» задача
двигает. Слитый проход одну половину делает дорогой, а вторую —
поверхностной. Отсюда и разные модели: doc-wording на sonnet,
task-form на opus. Первый подметает, второй судит смысл, и ровно на
суждении обкатка показала провал.
Каждый устав отказывается от чужой половины прямо: увиденное не по своей
части идёт строкой в границах покрытия, а не находкой. Две проверки
одного места расходятся и начинают спорить. Исключение ровно одно и
названо: неудачное слово в заголовке судит task-form, потому что
заголовок целиком его.
У task-form появилось шестое правило, которого не было ни у кого: связь
задачи со строкой «Завершения» её цели. Оно единственное читает больше
одного файла и единственное смотрит набор, а не запись — строка
«Завершения», к которой не относится ни одна поданная задача,
докладывается отдельным блоком. Это граница между вычиткой и разбором,
проведённая внутри правила.
Порог правки переехал в language.md помеченным домом «порог-правки» и
копируется в оба устава: правка без нарушенного правила не делается,
систематичность нарушения — не довод в его пользу. Дублировать его
руками значило бы получить два разных порога через месяц. Копий стало
шесть при пяти домах.
Порядок вызова — сперва task-form: его находки меняют решение «брать или
не брать», а язык меняет только цену чтения.
DECISIONS тема 23 (ССС–ФФФ, следствия 91–93).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Имя пришло из задач, но правила языка относятся ко всем проектным
текстам: документам канона, решениям ADR, запискам разведки. Форма
записи — вторая половина устава — верна только для файлов
docs/tasks/items/, и теперь это сказано заголовком раздела, а не
подразумевается. Вход расширен: список файлов или каталог, вперемешку
тоже.
Обкатка на тестовом наборе из 13 записей показала дыру в пороге
вмешательства. Агент нашёл, что раздел «Затрагивает» в нескольких
записях называет не только границу, но и её будущее состояние, — и
промолчал, объяснив это принятым стилем каталога. Записи писал один
агент за один заход: систематичность здесь значит ровно обратное —
правило не применялось вовсе. В устав добавлено: одна и та же ошибка в
пяти файлах даёт одну находку на весь набор с перечнем, но не даёт права
промолчать. Принятым стилем считается только то, что назвал зовущий или
что записано в конвенциях проекта.
Единственная находка агента попала в слово из собственного скилла. «Цель
про станок, а не про игру» — метафора, перенесённая в тестовую запись из
tasks/SKILL.md. Проверка показала худшее: «станок» в каноне уже занят,
«общий станок» это красная проверка, врывающаяся в замороженный спринт
(canon.md, session/SKILL.md). Одно слово в двух смыслах, тот же класс,
что и «окружение» в теме 19. Заменено на «работа над инструментом и
процессом» — как названа и секция роадмапа.
DECISIONS тема 22 (ППП, РРР, следствия 89–90).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Языковые правила лежали внутри скилла tasks: англицизмы, неизвестные
термины, «сложность формулировки — не признак сложности работы». Три
пункта из практики, без общей опоры и без ответа на «а что ещё сюда
относится».
Дом у языка теперь один — canon/references/language.md. Не в tasks, хотя
пришли правила оттуда: они относятся к документам канона, решениям ADR,
запискам разведки и сообщениям коммитов в той же мере, что к задачам, а
каталог задач и сам часть docs/. Раскладка отвечает, где текст лежит, —
этот файл отвечает, каким он должен быть словами.
Основа — информационный стиль Ильяхова, взятый не целиком. Взято:
полезное действие, глагол вместо отглагольного существительного,
активный залог, факт вместо оценки, стоп-слова, одна мысль — одно
предложение, параллельность, работающий заголовок.
Отброшенное названо вслух, и это отдельный раздел. Инфостиль написан для
текстов, где читателя надо удержать, а проектный текст читают потому,
что надо. Парцелляция ломает причинную связь, а в решении ценность
именно в ней. Запрет вводных целиком режет «если» и «в отличие от» —
условия, то есть сведения. Скобки в технической записи несут уточнение:
имя команды, единицы, слаг. Без этого раздела правило читается как «пиши
короче», и первый же агент начинает резать «поэтому» и «иначе».
«Снять корону с себя и надеть на клиента» переведено на здешнего
читателя: клиент — ты сам через квартал и тот, кто возьмёт задачу.
Таблицы англицизмов и жаргона взяты из скилла prepare-jira-text и
дополнены; в устав агента они уехали помеченной копией. Устав обязан
быть самодостаточным — он не разрешает пути плагина и не ходит по
ссылкам, — а два дома у одного правила здесь уже трижды расходились.
scripts/copies.py считает теперь 4 копии при 4 домах.
У агента вычитки правил стало двенадцать, разделены на форму записи
(только для задач) и язык (для любого проектного текста). Находки
докладываются в этом порядке: форма меняет решение «брать или не брать»,
язык — только цену чтения.
DECISIONS тема 21 (ЛЛЛ–ООО, следствия 86–88), changelog канона v3 —
пункт 6 и шаг переезда «прочитать и ничего не переписывать задним
числом».
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Обкатка скилла tasks на выдуманном проекте — консольные крестики-нолики
на JavaScript, каталог заведён с нуля тем же скриптом. Форма вылезла
раньше содержания, и правки все про неё.
Заголовок отвечает на вопрос типа записи, и форм три: цель —
утверждение о возможности, задача — глагол в неопределённой форме
(допускается «не» перед ним), идея — назывное, без обещания. Причина не
стилистическая: описательный заголовок называет состояние, а из
состояния не видно, чего от работы ждут — «Ничья объявляется, пока
клетки есть» одинаково читается как жалоба и как задание. Отсюда же
разница индексов: роадмап — список возможностей, беклог — список работ,
и перепутанные формы делают каждый похожим на другой.
Механизировано ровно то, что механизируется: check считает заголовки,
где первое слово не на -ть/-ти/-чь, и печатает число в блоке здоровья.
Замечанием на файл нельзя — эвристика грубая, а на 97 записях двух живых
проектов это поток одинаковых строк, после которого пропускают весь блок.
Годность формулировки судит отдельный агент task-wording, а не чек-лист
в скилле: сейчас формулировку пишет и проверяет один агент в одном
контексте, а самопроверка текста слабее всего там, где формулировка
казалась удачной при написании. Он ничего не правит — возвращает готовые
формулировки, и заголовок с «зачем» показываются человеку, потому что
по ним задачу выбирают. Ничего из того, что ловит tasks.py check, он не
трогает намеренно: это был бы второй дом для правила.
Заголовки секций — с прописной, после заголовка пустая строка, во всех
индексах. Канонические имена стали Готово | Запланировано | Направления
| Разработка (англ. Done | Planned | Directions | Tooling), сверка везде
по нижнему регистру, так что старые индексы читаются по-прежнему.
Отбивка живёт на записи, а не на вставке: через Plan.index проходит
каждая правка индекса, а мест вставки три.
Имя секции принадлежит заголовку индекса, файл на неё только ссылается.
Это разрешает единственную неоднозначность починки — расхождение в одном
регистре правится в пользу заголовка. Без него переезд на канон оставил
бы «Готово» в роадмапе и «готово» в каждом файле цели, и свести это было
бы некому. Регистр правится только у канонических секций: имена секций
беклога выбирает проект.
Обкатка нашла два дефекта, которых не находили ни линтеры, ни свои
проверки. Вставка в пустую секцию съедала отбивку перед следующим
заголовком — пропуск пустых строк теперь идёт только до первой непустой.
Мета, разорванная пустой строкой, теряла поля молча: check видел лишь
следствие («без рода работы») и советовал edit --kind, который дописывал
второе такое же поле. Поле меты в теле стало ошибкой с названной
причиной, и --fix её намеренно не чинит — какое из двух значений верное,
знает человек.
DECISIONS тема 20 (ЕЕЕ–ККК, следствия 82–85), changelog канона v3
пополнен двумя пунктами и двумя шагами переезда, TODO — два шага для
healthlog и jellybit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
готово | запланировано | направления | разработка, англ. 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>
«Идентичность, слияние, разбор» пришли из одного проекта, и в общем виде
формулировка не читалась: вопрос «как применить это к моему проекту» не имел
ответа в тексте. Теперь класс задан тремя условиями, не зависящими ни от
домена, ни от языка: вариантов несколько и оба защитимы; спека между ними не
выбирает; неверный выбор не падает, а даёт правдоподобный результат и молча
меняет смысл данных.
Отрицательный тест сильнее трёх положительных: то, что красит гейт, роняет
запрос или ломает тест, в класс не входит — это ловят проходы дешевле. Отсюда
же и причина, по которой класс достался самому дорогому проходу: независимая
реализация выберет другой вариант, и дифф между вариантами и есть находка; там,
где вариант один, она совпадёт с существующей.
Три слова остались как три места, где такие правила водятся — граница, где
данные входят или встречаются: состав ключа и нормализация перед сравнением;
победитель конфликта и тай-брейк при равенстве; границы токенов и неоднозначный
вход. Проект перечисляет свои места в docs/review.md, и перечень производен от
теста, а не заменяет его.
Две оговорки, без которых правило вырождается:
- триггер — новое или изменённое по существу правило, а не код рядом с ним;
иначе проект, чей домен и состоит из таких правил, всегда в deep;
- проект, где такого класса нет вовсе, deep не запускает никогда, и это
законное состояние, а не недонастройка.
review-reimpl получил тот же тест и право сказать первой строкой, что позвали
не на его класс, — строкой в границы покрытия, а не отказом работать.
DECISIONS 18, XXX и следствия 76–77.
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>
Тема 17, решения HHH–QQQ и следствия 68–71. Отдельной строкой — что версию
канона 3 занял роадмап с родом работы, поэтому отложенное решение темы 16
(каталог вместо файла в docs/) вводится версией 4; поправлено в обоих
местах.
TODO раздел 6: повышение healthlog и jellybit до канона 3. Оба стоят на
версии 2 с живым PLAN.md — 55 и 43 задачи, — так что переименование это не
свободная правка, а миграция по журналу версий. Род работы и «Затрагивает»
там проставляются не задним числом: сперва то, что идёт в ближайший набор,
остальное по ходу переоценки.
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>
Прыжок standard → deep стоил самого дорогого прохода конвейера, а платить
приходилось за одну архитектурную находку: изменений, которые трогают
публичный контракт, но не вводят нового правила слияния, — большинство.
Ступень wide это standard плюс architecture (вход шире диффа, отсюда имя),
семь проходов против восьми.
Заодно вычистилась давняя неровность: триггер reimpl стоял внутри deep, и
профиль означал то семь проходов, то восемь — реестр состава, который
«сверяется взглядом до коммита», проверять было нечем. Теперь условие
«новое правило идентичности, слияния или разбора» выбирает профиль, reimpl
в deep безусловен и есть единственное отличие от wide. Барьер стоимости
остался только в deep: в wide за ним стоял бы один дешёвый проход с
потолком в 3 находки, а барьер сериализует то, что могло идти разом.
Цвет charter'а теперь кодирует модель, а не роль: sonnet → green,
opus → yellow, fable → red. Роль видна из имени, стоимость прогона —
ниоткуда, а список агентов читается взглядом.
scripts/frontmatter.py ловит три класса ошибок, невидимых при чтении:
- двоеточие с пробелом в незакавыченном описании — для YAML это вложенное
отображение, а не текст. Так было написано три описания из четырнадцати,
и читались они правильно;
- name, разошедшееся с именем каталога скилла или файла charter'а;
- цвет, не отвечающий модели: он ставится один раз при заведении charter'а,
а модель потом двигает калибровка.
Обе ветки проверены, коды выхода — общий словарь. Триггеры профиля в
canon.md и skeletons.md подтянуты под wide.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Тема 16. Порог в строках триггером не становится: единственный документ
у порога — healthlog/docs/architecture.md, 1662 строки, но в нём десять
маркеров долга, а разделы «Слои гранулярности», «Тренировки и прочие
секции», «Свёртка и размер ответа» — поведение, чей дом openspec/specs/,
где уже лежат пять capability. Порог сработал бы там, где надо доводить
переезд, и дал бы долгу постоянное жильё.
- шов выноса — другой читатель или другой срок жизни: review.md
(настройка стабильна, журнал растёт) и architecture по «окружение,
деплой, наблюдатель»; расщепление по решениям отвергнуто — у «почему»
дом adr/; security.md и passport.md остаются файлами;
- вводить — только с одной точкой входа: <имя>/README.md и есть прежний
документ, каждый файл каталога достижим ссылкой из него (ловится
сегодняшним check_links). docs/architecture.md упомянут в репозитории
66 раз, развилка «файл или каталог» размножится на девять charter'ов;
- решение после переезда healthlog: замерить остаток, жмёт — канон
версии 3. TODO шаг 2 дополнен пунктом, 1611 строк исправлены на 1662.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Актуально для av-dev-backlog: плагин устарел и снимается с проекта по
мере перевода задач на docs/tasks/. Порядок обязателен — сначала canon,
потом uninstall, иначе проект остаётся со старой раскладкой и без
скилла, который её понимает.
Проверено на одноразовых проектах, не выведено из документации:
- uninstall правит два места — enabledPlugins в settings.json проекта и
запись в installed_plugins.json; кэш-снимок и extraKnownMarketplaces
не трогает;
- вызванная не из проекта, команда отказывается словами is not installed
in project scope, а не снимает наугад, как plugin update;
- ручная правка settings.json не убирает запись реестра, но та же
команда добирает её и при уже пустом enabledPlugins.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Обновление вынесено отдельным разделом, потому что главное в нём —
шагов два, и первого мало: marketplace update тянет git-клон, а снимки
плагинов лежат в ~/.claude/plugins/cache/<маркетплейс>/<плагин>/<версия>/
и двигаются только plugin update. Один шаг без второго выглядит как
«обновил, а ничего не изменилось».
Проверено на этой машине, а не выведено из документации:
- cd в проект обязателен — вызов двигает одну запись реестра; av-dev-git
стоит в шести проектах, вызов из dev-skills поднял версию ровно в
одном, и не в том, откуда звали;
- plugin update идемпотентен: на свежем плагине говорит already at the
latest version;
- сниппет со списком установленного скопирован из README и выполнен
через bash — работает как написано;
- версия реестра это первые 12 знаков хеша коммита, поэтому в тексте
git rev-parse HEAD | cut -c1-12, а не git log --oneline.
У install и marketplace add умолчание scope — user, и без --scope project
плагин уедет не туда, куда указывает settings.json проекта; сказано в
самих командах. Абзац про снос проектных копий вернулся под «Подключение»:
он про установку.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Диаграмма и проза вокруг неё описывают один факт — это второй дом, и
разойтись они могут молча: то самое, против чего написан copies.py.
Механической сверки здесь нет, дословного соответствия между текстом и
графом не существует, поэтому работает объявление. В review-pipeline
старший граф — он и есть алгоритм планировщика, проза объясняет рёбра;
в остальных местах старшая проза, диаграмма там сводка; в calibration.md
старшая таблица вердиктов, схема добавляет к ней только счётчик.
Объявление стоит у каждой диаграммы строкой в месте, а не общим правилом
в README: скилл читают целиком, README — нет. В task-batch добавлена
оговорка про соседний скилл — два вызова с разным старшинством рядом это
место, где легко ошибиться.
scripts/diagrams.py вынимает все mermaid-блоки и рендерит каждый через
mmdc или npx @mermaid-js/mermaid-cli. Коды выхода — общий словарь; нет
рендерера — код 3, а не молчаливый успех. Chromium с --no-sandbox:
без флага падает на «No usable sandbox», причина в докстроке. Проверены
обе ветки: 11 диаграмм в 9 файлах зелено, сломанный блок даёт точное
место с текстом ошибки парсера и код 1.
README: раздел «Проверка диаграмм» рядом с проверкой копий — что ловит,
чего не ловит и почему не в гейте. DECISIONS 63 и 64.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Критерий: диаграмма заводится, если структура граф или автомат, а проза
вынуждена его пересказывать. Где структура таблица соответствий — чек-лист
синка, профили ревью, коды выхода — не заводится: дублировала бы таблицу
и разошлась с ней.
tasks: жизненный цикл записи по индексам — состояния это где числится
строка, файл items/ не двигается ни на одном переходе.
session: четыре шага сессии; текст говорил «это зависимость, а не список»,
но зависимости не показывал — теперь на рёбрах написано, что ломается.
sprint.md: исходы задачи в спринте плюс два ребра, где порядок нарушается
молча — урожай до sprint close и блокер в обход исходов.
task-pipeline: одиннадцать шагов с развилкой «тривиальная» и досрочным
исходом «крупнее задачи».
promote.md: храповик находка → конвенция → правило → удаление, с обратным
ребром; обязательность третьего шага теперь видна как ребро.
calibration.md: счётчик retune до drop — таблица вердиктов его выразить
не может, автомат может.
README: граф вызовов между плагинами; односторонность зависимости
pipeline → pm видна сразу.
Все девять блоков прогнаны через mermaid-cli. README-схема и автомат
калибровки переверстаны после просмотра: subgraph'ы ломали раскладку,
self-loop наезжал подписями.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Номер стадии не означал зависимости: между стадиями 1–4 ни один проход
не читает вывод другого, и очередь между ними была платой ни за что.
А правило про замеры держалось на двух именах и рассыпалось бы в день,
когда мерить начнёт третий проход.
Рёбер три вида, и они разной природы: зависимость (гейт → опиниативные,
все проходы → триаж), конфликт за ресурс (ненаправленный) и барьер
стоимости. Стадии остаются единицей состава, порядок задаёт граф:
уходит всё, у чего входящие рёбра закрыты.
Сериализует ресурс, а не имена: пометка «держит машину» — gate,
adversary, ops, triage; остальные читают и рассуждают. Проект вправе
пометить свой проход, снять пометку с перечисленных — нет.
Ранний выход заменён барьером стоимости и стоит там, где выход
зарабатывал: перед reimpl и architecture, то есть только в deep.
Отдельным абзацем — что ребро значит порядок и никогда не данные:
графовый словарь провоцирует обратное прочтение, а проход, увидевший
чужие находки, соглашается с ними. Исключение одно и оно же сток.
Диаграммы — mermaid, прогнаны через mermaid-cli. Режим прогона теперь
«по графу» / «линейно»; task-batch и task-pipeline подтянуты под общий
словарь, adversary и ops знают о пометке из своих charter'ов.
DECISIONS 15.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Умолчания разошлись по цене шага. Проход ревью читает и рассуждает: он
ничего не поднимает, ни за что не дерётся и по построению не видит
выводов соседа — очередь между проходами добавляет только ожидание.
Задача батча тянет полный цикл пайплайна с гейтом, поднятием сервиса и
вложенным ревью — две такие дерутся за порты, каталоги и железо.
review-pipeline: параллельно внутри стадии — умолчание. Последовательно —
по трём причинам с именем в отчёте: сказал оператор, проходы меряют,
машина занята. Просьба «последовательно» набора не требует. Меряющая пара
adversary + ops стала именованным исключением: она идёт по очереди
всегда, и общее «гони параллельно» этого не отменяет. Ранний выход
переехал на границу стадии.
task-batch: план собирается графом зависимостей и в умолчании
линеаризуется. Параллельно — по просьбе, и просьба разрешает ширину
графа, а не «всё разом»; потолок 2–3 и одиночная волна замеряющей задачи
сохранены как правила этого режима. Режим ревью внутри задачи выводится
из режима батча и называется в charter'е. Финальная сверка гонит
review-specs по capability параллельно.
DECISIONS 14 — с причиной; версия канона не меняется, канон этих скиллов
не описывает.
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>
Последнее место, где поля писались одной строкой через ·: цель, дата начала и
слаг спринта. После переезда меты задачи в блок эта строка осталась
единственным исключением, а объяснять два формата дороже, чем иметь один.
Старая шапка читается по-прежнему — GOAL_LINE берёт строку и с ведущим «- »,
SPRINT_SLUG_LINE и раньше искала по всей строке. Починки для неё нет и не
нужно: SPRINT.md переписывается целиком на sprint start и очищается на sprint
close, так что старая форма живёт не дольше идущего спринта.
Форма заодно описана в task-format.md — до сих пор она жила только в коде,
и человек, читавший документ формата, о ней не узнавал.
Проверено на временном проекте: start → take → check → подсунутая старая
шапка → drop → close; цель и слаг читаются в обеих формах.
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>
092d07c..88c5d97, клон встал на ту же ревизию и видит av-dev-pm и
av-dev-pipeline. Предусловие переезда healthlog снято: подключать теперь есть
что.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Шапка и пункт про push стояли на 11 коммитах и восьми темах — стало 17 и
двенадцать. Предел «копия правила в шаблонах» теперь говорит, что расхождение
ловит copies.py, а на человеке осталось пометить копию и завести запись в
журнал версий.
В план healthlog дописан снос девяти проектных агентов и двух скиллов: они
прошлого поколения и ссылаются на docs/conventions.md, docs/local-research.md
и docs/review-journal.md — на файлы, которых после переезда не будет.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Разделение плагинов оставлено, цена названа: пять симметричных контрактов в двух
домах, два уже разошлись — форма журнала дефектов потеряла в копии поле
«Причина», список читателей docs/research/ потерял specs. Оба раза копия
выглядела актуальной и прошла мимо трёх ревью.
scripts/copies.py требует побайтового совпадения текста между маркерами.
Комментарии, а не манифест копий: маркер уезжает в репозиторий проекта вместе со
скелетом и там полезен — говорит, что у текста есть дом.
Идентификатор строгий и повторяется в закрывающем маркере. Иначе документация о
самом механизме объявляет дом и роняет проверку: это случилось на первом же
прогоне, README объявил дом примером.
Ограда блока кода в сверку не входит: в доме текст обрамлён своей оградой, в
скелете лежит внутри чужой, объемлющей.
Помечены два контракта. Второй пришлось сперва сделать дословным: копия говорила
«обязателен статус», дом — «обязателен статус „заменено на“».
Проверка не ловит копию, которую забыли пометить, — это сказано вслух, иначе
зелёный прогон читался бы как «копий больше нет». И не заменяет запись в журнал
версий канона: она видит, что копия отстала, но не что проект унёс старую версию.
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>
Два независимых сабагента на 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>
Скрипты остаются на голом python 3.12 без зависимостей: pyproject.toml живёт
только в этом репозитории и держит линтеры, а не зависимости скриптов.
Ноль зависимостей охраняется дважды: banned-api у ruff ловит частые соблазны по
имени, pyrefly видит окружение без ничего и не разрешает любой сторонний импорт.
Версии прибиты точно, uv.lock под git: обновление линтера меняет набор находок,
а находки правятся руками в скриптах, которые уезжают в чужие проекты.
RUF001–003 выключены — весь текст русский, 311 срабатываний из 338 шум.
av-dev-backlog исключён: заморожен до удаления, правка без выгоды.
Из 41 находки содержательных две: мёртвая ques в check и два места, где
find_entry_index может вернуть None прямо в list.pop и range. По ревью там
стоит raise, а не continue: тихий пропуск превратил бы сломанный инвариант в
отчёт «индексы согласованы».
os из tasks.py ушёл целиком, fail() в docs.py объявлен NoReturn.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- sprint.md прямо запрещал шаг, который пайплайн теперь делает: раздел «кто и
когда закрывает» переписан под снятую границу приёмки
- закрытие задачи стало шагом 11, после коммита: раньше упавший коммит оставил
бы задачу закрытой без следа работы
- контракт close --implemented больше не обещает состоявшуюся приёмку
- слот «куда копируются критерии приёмки» убран из session: на него отвечает
пайплайн, а канон его не заводил
- research/ в таблице ролей вернул adversary; журнал версий поднимает CLAUDE.md
целиком, а не тремя пунктами из восьми
- TODO и REMAINING перестали занижать: коммитов одиннадцать, переписок три
- task-pipeline и task-batch запрещали шаг, который сами же добавили: раздел
границ и финальный доклад переписаны под снятую границу приёмки
- «триаж сводит строки в одну» противоречило «не сливает» — деградация снова
поразрядная во всех трёх местах
- канон не требовал в CLAUDE.md имени основной ветки, testdata и запретов, а
скелета CLAUDE.md не было вовсе — заведён
- обратимость жила в двух домах, читатели ходили в пустой; единственный дом
теперь CLAUDE.md
- заведены слоты «Единые точки проекта» и «Триггеры профиля», куда charter'ы
слали, а канон их не создавал
- блок «Вопросы к проходам» стал частью задания прохода: за ним ходили двое
из девяти
- чек-лист синка и правило «замер + настройка» сведены к одному дому;
plugin.json больше не про бриф
- README: три плагина, канон документов, явное обновление маркетплейса
- HISTORY: сжатый AGENTIC-TASKS — что отвергнуто и почему, числа первого замера
- REMAINING: главным риском названа несделанная калибровка при двух подряд
переписываниях charter'ов; закрытые разбором вопросы убраны
- удалены скилл project-brief и контракт брифа; вместо них references/
project-facts.md — карта «что нужно проходу → где лежит» и таблица
поразрядной деградации по документам
- девять charter'ов, review-pipeline, task-pipeline и task-batch переписаны
на пути канона; OpenSpec стал объявленной предпосылкой без ветки деградации
- шаг синка документации переписан в построчный доклад, закрытие задачи —
вызовом скилла av-dev-pm:tasks вместо строки-слота из CLAUDE.md
- по находкам ревью: docs.py звал tasks.py из чужого каталога и выдавал его
отказ окружения за дрейф; сверка миграций не видела рабочее дерево;
плейсхолдер краснел вместо замечания; сверка capability проходила по
совпадению с именем пакета; tasks.py не читал docs/.pm.json; скилл docs
пересказывал канон в пяти местах
- av-dev-tasks → av-dev-pm; канон определён единственным reference-файлом,
который читают все три новых скилла
- canon: check/adopt/upgrade плюс docs.py — раскладка, битые ссылки, версия,
маркеры долга, сверки миграций и capability с документацией
- tasks и session: путь docs/tasks жёсткий, конфиг переехал в docs/.pm.json,
слот «Команда учёта задач» убран в пользу вызова скилла, раздел «Стимулы»
переписан под совпавших приёмщика и исполнителя
- DECISIONS.md: 29 решений по восьми темам, каждое с причиной; две отменённые
версии сохранены с объяснением отмены
- TODO.md: план в порядке выката, замер блокирует переезд jellybit
- скилл project-brief: бриф собирается из CLAUDE.md, архитектуры, Taskfile
и конвенций и показывается человеку. Раньше единственная инструкция по
его созданию лежала внутри шаблона, поэтому деградированный режим был не
аварийным, а единственным: critical по основанию «нарушен инвариант»
недостижим ни на одной задаче
- rebase перенесён внутрь worktree задачи: прежняя форма падала на занятой
ветке, и агент уводил весь батч в провалившиеся с ложной причиной
- контракт брифа дополнен восемью слотами; проверен заполнением на обоих
проектах, незаполнимых нет. Прецедент healthlog вынут из общего charter'а
в бриф — там он вмёрз вместе с числами
- шов: пайплайн задачу не закрывает и записи учёта не трогает, урожай
отдаёт списком, правило остатка — ссылкой на av-dev-tasks
- деградированный абзац во всех девяти проходах, вопрос 9 в ops,
пространство имён в вызовах, раздел предпосылок
- атомарность: sprint drop и move собирают план правок целиком и пишут
одним проходом; раньше отказ на втором слаге оставлял первый файл
переписанным при нетронутом индексе
- хук переехал в мета-строку файла: индекс стал производным, и check --fix
больше не теряет текст, восстанавливая строку
- механизировано то, что было записано, но не проверялось: слаг спринта и
автотег, отказ по факту непустого раздела вопросов, число критериев,
пометка decomposed, покрытие причин
- reopen возвращает закрытую задачу: без него порядок «пайплайн доложил →
приёмщик судит → владелец закрывает» был односторонним
- скилл adopt: приходит в чужой репозиторий и выводит заполненный каталог
задач. На копии беклога healthlog — 12 целей, 38 задач, 36 переименований,
86 ссылок в 36 файлах, check зелёный
Пара плагинов с намеренно проведённой границей: av-dev-tasks отвечает
за то, что делаем и в каком порядке, av-dev-pipeline — за то, как ведём
одну задачу. Зависимости между ними нет: управление задачами работает и
с ручным исполнением, пайплайн — на проекте с любым учётом задач.
- av-dev-tasks — преемник av-dev-backlog: цели вместо приоритетов,
спринт под одну цель с заморозкой набора, различение вопроса и
блокера, каденция «вопросы — разбор — переоценка — набор».
Раскладка docs/tasks с items/, PLAN.md, BACKLOG.md, SPRINT.md,
REJECTED.md; проверенное из av-dev-backlog перенесено, не переписано.
- av-dev-pipeline — вынос того, что лежало копиями в healthlog и
jellybit (3628 строк) и уже разошлось: цикл SDD, конвейер ревью с
обязательным триажем, прогон нескольких задач разом. Проектная
специфика вынесена в файл-бриф, charter'ы несут метод.
Коммит фиксирует состояние на момент ревью: три прохода нашли
блокирующие дефекты (нет шага, заводящего бриф; git rebase на занятой
worktree ветке; sprint drop пишет наполовину) — они чинятся следующими
коммитами. Сохранено как база, от которой видно правки.
- скилл commit кодирует личный стиль сообщений: русский, опциональный scope-префикс, первая строка «что сделано», тело 1–3 пункта, без co-authored
- плагин добавлен в marketplace.json и в секцию README
git-сервер доступен по https, а CLI `plugin marketplace add` не принимает
ssh://…:2222 (только owner/repo, https, ./path). Переводим все примеры на
https://git.vakhrushev.me/av/dev-skills.git; в JSON-блоке source-тип "git"
(ровно то, что пишет команда add).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Добавлены команды с --scope project (/plugin и claude plugin) — пишут прямо в
.claude/settings.json; user-scope формы оставлены как разовая установка себе.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ведущий способ подключения — через .claude/settings.json проекта
(extraKnownMarketplaces + enabledPlugins по git-URL), чтобы плагин был активен
у всех, кто открывает репозиторий. Интерактивная установка через /plugin —
как разовая альтернатива. Локальный путь заменён на реальный remote.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Соглашение об именах: длинное имя плагина с префиксом av-dev- (уникально в
маркетплейсе), короткие имена скилов внутри. Вызов — /av-dev-backlog:backlog,
единообразно для будущих плагинов.
Путь к backlog.py в SKILL.md обновлён под новую раскладку
($CLAUDE_PLUGIN_ROOT/skills/backlog/scripts/backlog.py).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Отдельный репозиторий-маркетплейс для личных плагинов и скилов разработки,
чтобы подключать их к проектам через `/plugin`, а не держать в глобальном
`~/.claude/skills`.
Первый плагин — backlog: перенесён скилл ведения беклога из
`~/.claude/skills/backlog` под именем `av-dev-backlog`. Путь к `backlog.py`
переведён с фиксированного `~/.claude/...` на `$CLAUDE_PLUGIN_ROOT`, чтобы
работать после установки плагина.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>