- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель;
- буквенные метки решений заменены сквозными Р1–Р234, следствия получили
префикс С при прежних номерах: схема букв выродилась до пятибуквенных и
сломалась — `АЕАКЛ` была занята и темой 53, и темой 65;
- 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер
означал тему, а слово стояло «решение», формулировка исправлена.
README переписан под два плагина: состав скиллов с префиксами, диаграмма одним
контуром, команды установки и обновления, раздел версий про .av-dev.toml. Правка
про копии сказала главное — копия была платой за неразрешимый путь, а не за
важность правила, и внутри одного дерева остаётся только там, где текст обязан
лежать в промпте.
DECISIONS: тема 64 с замером цены раскола и четырьмя следствиями. Довод «а вдруг
понадобится» снят наблюдением: режим, ради которого раскол держали, покрыт
сценарием обслуживания.
Каталоги, агенты и общие дома переехали в av-dev/; скиллы названы по прежнему
плагину — doc-*, task-*, code-*, с двумя смысловыми именами вместо тавтологии:
doc-sync вместо docs, task-track вместо tasks. Манифесты сведены к двум
плагинам. Пространства имён вызовов и пути внутри дерева переписаны машинно;
проза, которая называет прежние плагины отдельными, идёт следующим шагом.
Задача, не меняющая поведения (тулчейн, зависимости, сборка, гит-хуки, перенос,
чистка), шла полным циклом решения. Все его шаги стоят на дельта-спеках, а у
chore их нет по построению: цикл не урезан ради дешевизны, он остаётся без входа.
Признак — связка: тип записи предлагает, отсутствие дельт подтверждает, а
расхождение признаков это стоп. Размер признаком не стал намеренно: «мелкое —
коротким путём» и есть самая дешёвая лазейка. Планового стопа у сценария нет
вовсе — объяснять человеку нечего, выбора там не делают; правило необратимого
поэтому действует жёстче, чем в двух других.
Ревью идёт фиксированным планом без метки и без разметчика — autotests и
operations, плюс conventions с техническим разбором, когда дифф трогает код.
Конвейер получил раздел «Прогон без change»: он написан вокруг change, и без
этой строки вызов упирался бы в предпосылку OpenSpec. Главный шаг сценария —
синк документации, а триггеры ADR работают стоп-признаком: своего источника у
обслуживания нет, и решение с ценой уходит в разведку.
Разведка была прологом к коду: три шага, чекпоинт вариантов — и вливание в
общую ветку. Своего исхода у неё не было, поэтому и писать в документы проекта
ей было незачем: ответ оседал в design.md будущего change.
- у разведки появился исход: ответ уезжает в документы канона, задачи заводятся
и уточняются, написанное коммитится, запись закрывается. Кода сценарий не
пишет вовсе, OpenSpec ему не нужен
- точка входа осталась одна, и сценарий выбирает скилл, прочитав постановку:
«есть ли очевидный способ решения» видно после чтения записи, и требовать
этого суждения от вызывающего значит требовать его раньше, чем оно возможно
- оба сценария лежат справочниками и одинаково — solve.md и research.md, — а в
SKILL.md остались вход, развилка и правила, не зависящие от сценария.
Асимметрия читалась бы как старшинство: сценарий в теле скилла выглядит
основным, а в справочнике — оговоркой
- переход между сценариями — событие с названным исходом: решение, упёршееся в
незнание способа, останавливается; разведка, выбравшая способ, доводится до
конца, а код идёт следующим прогоном, который запускает человек
- канон 14: у ADR два законных источника. У решения, принятого разведкой,
design.md нет по построению, и такое решение либо не попадало в adr/ вовсе,
либо попадало сочинённым заново
Правки по своему же ревью, до коммита:
- версия 14 была неполной — разрез проверки, вход и устав doc-consistency,
скелеты adr/README.md и template.md по-прежнему требовали ссылку на
design.md. Агент краснел бы на законной записи; скелеты уезжают в проекты,
поэтому запись журнала называет их поимённо
- canon.md объявлял себя двенадцатым, пережив версию 13. Литерал был третьим
домом числа при двух исправных — убран, а не поправлен
- сценарий разведки был недостижим там, где обещал работать: ready требует у
research оба раздела, включая «Куда ляжет ответ», а сценарий брался назначить
адрес сам. Адрес назначает автор записи; сценарий — только когда записи нет
- разведка коммитила без гейта, хотя правит документы канона и индексы задач
- при переносе выпало предупреждение про закрытие разведки без записанного
ответа — возвращено
Имя `.pm.json` пережило плагин `av-dev-pm` на два месяца и указывало в пустоту.
Правило, которое из этого вынуто: имя служебного файла — имя плагина, который
его завёл, и по нему же владельца узнают.
- `docs/.pm.json` → `docs/.docs.json`, запись 13 журнала. Прежнее имя docs.py
не читает намеренно: по этому числу upgrade решает, какие записи применять,
и два дома разъехались бы молча ровно там, где это дороже всего. Вместо
совместимости — узнавание: check видит старый файл и печатает готовую git mv
- у каталога задач появилась своя версия формата — ключ `tasks` в
`.tasks.json`, свой журнал версий и своё повышение. До сих пор её не было
вовсе, хотя docs.py в комментарии уверенно на неё ссылался: описание
опережало механику ровно так, как сказано в решении 195
- число своё, а не копия канонического: плагин ставится в одиночку, и у
проекта без docs/ версии канона нет — сверять было бы не с чем
- конфиг задач стал обязательным (init и adopt apply пишут его всегда), check
сверяет число, `check --fix` его не приписывает: приписанное объявляло бы
каталог приведённым к формату, шагов которого никто не делал
- переезды 11 и 12 в новый журнал задним числом не переписаны — версия 1
велит догнать формат по журналу канона, называя признаки отставания
поимённо (каталог в docs/tasks/, живой SPRINT.md)
- запись 60 в DECISIONS со следствиями 200–203; отдельно разведено с решением
F, где `.docs.json` отвергался как указатель путей: отвергнут был указатель,
а не имя
- дом «что механизировано» называл conventions/README.md, хотя документ канона
живёт файлом или каталогом; копия пересобрана resync
- запись 59: находки одного рода — правил механику, не правил описывающее её
вовне. Пять выводов, включая «скелет не описывает, а порождает»
- в план добавлена пачка мелочи, оставленной сознательно, и сказано, что
бумажная часть закрыта
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
doc-consistency и doc-code-drift звались шагом сессии между спринтами.
Сессия стала грумингом, груминг судит задачи, а не документы, и звать
чужих агентов не вправе — они в av-dev-docs. На живом проекте их не
звал бы никто, кроме разовых adopt и upgrade.
Момент назван у владельца. Разрез с canon check проверяемый: машина
сверяет форму, healthcheck — утверждения.
Почему скилл, а не просто описания агентов: двоим нужна оркестровка —
позвать обоих на весь канон разом, передать doc-code-drift раздел
запретов, разобрать урожай порциями, назвать границы покрытия и кого
именно позвал. Этого агент о себе не знает.
doc-wording внутрь не взят: ему оркестровка не нужна, и ритм другой —
он нужен там, где текст только что писали.
Заодно из shared/plugin-boundary.md и README убран счётчик скиллов: он
протух дважды за день.
resolve судил готовность записи глазами — текст писался до того, как
появилась команда ready. Теперь зовёт её через av-dev-tasks:tasks, а
отказ читает исходом «не доведена». Это ровно тот случай, где машина
дешевле и точнее, а цена ошибки отложенная.
canon.md всё ещё говорил, что невзятой запись делает sprint take.
REMAINING перечислял три опоры против совпадения приёмщика с
исполнителем, включая SPRINT.md под git. Опор осталось две, и третья не
заменилась, а исчезла: у приёмки больше нет момента. Записано как есть.
frontmatter.py: устаревший путь review-pipeline/SKILL.md в комментарии.
В план добавлена дыра, которую открыло снятие сессии: двух агентов
канона на живом проекте больше не зовёт никто, кроме adopt и upgrade.
Предмет сузился до двух: что сейчас самое важное и что перестало быть
важным. Ответ записывается порядком строк в беклоге.
Из четырёх шагов сессии выжили два (вопросы, переоценка порциями), один
заменился расстановкой очереди вместо набора спринта, два выпали.
Приёмка — грумингу не по предмету, ритуала у неё больше нет, остаётся
reopen; цена названа в тексте. Разбор процесса потерял якорь, и вместе
с ним ушёл прямой вызов агентов doc-consistency и doc-code-drift — это
починка, а не потеря: агенты принадлежат av-dev-docs, и груминг звал их
мимо правила обращения к соседу.
sprint.md удалён, cadence.md стал portions.md.
Канон 12: запись в журнал велит проектам снести SPRINT.md и расставить
порядок, с точным порядком шагов — сперва удалить файл, потом check
--fix, иначе он увидит третий индекс и станет ругаться, а не чинить.
Побочно: canon.md объявлял себя версией 7 при текущей 11. Пять версий
дом канона врал о себе — машина сверяет константу скрипта, а прозу в
заголовке не читает никто.
Имя описывало устройство, а не предмет: «пайплайн» говорит, что внутри
конвейер, — а плагин занят кодом по задачам, и с появлением чекпоинтов
он уже не конвейер в чистом виде. Набор имён стал параллельным:
docs / tasks / code / git, каждое называет материал.
Заодно review-pipeline стал review — слово ушло из плагина целиком, а
не наполовину; скиллы выровнялись: resolve / review / openspec.
Журнал версий канона переписан вместе со всеми, DECISIONS.md — нет.
Разрез по типу высказывания, а не файла: наблюдение и причина
неприкосновенны, предписание и адрес обязаны оставаться исполнимыми.
Запись версии 10 велит «проверить, что плагин av-dev-pipeline
установлен» — проект, дошедший до неё, выполнил бы невыполнимое.
Автоматическое решение задач агентом работает плохо, и хуже того — в
процессе перестаёт ориентироваться автор. В цикл возвращается человек,
но не согласованием на каждом шаге: доктрина «делать, а не спрашивать»
не отменена, а ограничена местом. Развилка до ближайшего чекпоинта
копится в него, после последнего — уходит вопросом в запись.
Чекпоинтов два. «Варианты» — у исследовательской задачи, до первого
требования: 2-4 способа с ценой каждого и рекомендацией, выбор оседает
по адресу, который назвала сама запись. «Объяснение» — у всякой, после
ревью дизайна: человек читает просеянное машиной.
Объяснение не завело своего артефакта — оно собирается из proposal.md и
design.md, а требование к их форме уехало в openspec/config.yaml
(rules.proposal, rules.design), то есть применяется в момент написания.
Отдельный раздел был бы третьим домом одного объяснения.
Закрыт открытый вопрос: находка ревью, меняющая дельта-спеки, отменяет
одобрение — разметка пересчитывается, чекпоинт повторяется.
Пайплайн нескольких задач снят с повестки: работаем по одной. Каталог
скилла удалён, и с ним всё, что держалось только на нём.
Хвосты были не только ссылками. У review-specs исчез третий режим
(стык после слияния) — вместе с исключением «живого change нет, берём
актуальные спеки источником»: теперь отсутствие дельта-спеки это отказ.
У review-triage исчезло единственное исключение из правила «плана нет —
не запускаюсь». В каноне и у doc-code-drift имя основной ветки
обосновывалось тем, что «в неё вливает батч», — довод заменён на
верный.
Адрес принадлежит одному плагину, а называют его все: docs/* стоит в
сорока местах конвейера, tasks/ROADMAP.md — в четырёх местах канона.
Переименование в каноне до них не доходит, и заметить это нечем:
протухший адрес попадает в механизм честной деградации ревью и выходит
правдоподобной строкой «документа в проекте нет», а не поломкой.
Перечень берётся из константы владельца — той, по которой он и так
проверяет раскладку. Судится упразднённое, а не незнакомое: список тем
канона открытый, и «нет такого имени» опровергнуть нечем; зато карта
переездов RETIRED и есть перечень запрещённого. Рядом одна догадка —
почти совпавшее имя как опечатка, порог замерен (законные до 0.64,
опечатки от 0.91).
Первый прогон: одна настоящая находка — REMAINING иллюстрировал
смысловой дубль адресом docs/specs/, упразднённым в версии 1 канона.
В гейте без glob: перечень лежит в .py, упоминания в .md, и коммит с
переименованием трогает только первую сторону.
Стояло в пяти местах в пяти редакциях: два разных довода, ни в одном
месте оба, и три места из пяти молчали о том, что делать при
неразрешившемся вызове. Плюс невысказанный инвариант: $CLAUDE_PLUGIN_ROOT
ведёт только в свой плагин.
Дом — shared/plugin-boundary.md, блок «граница-плагинов», семь помеченных
копий. В дом вошло правило, последствия остались на местах вызова:
«нет плагина задач — учёт остаётся владельцу» знает только конвейер.
Оглавление адресов в CLAUDE.md проекта отклонено — второй дом раскладки,
и протухший адрес в нём выходит правдоподобной строкой честной
деградации. Сверка адресов уходит машине, записана в TODO разделом 5.
План описывал мир до раскола: av-dev-pm в живых, каталог задач в docs/, шаги
повышения на каноны 3, 4 и 5 — при том что канон уже 11. Двести с лишним строк, из
них живых полтора десятка, и найти их можно было только прочитав всё.
Умер он двумя способами сразу, и оба записаны в новом заголовке, чтобы не
повторились. Первый: сделанное помечалось галочкой и оставалось в файле — список
из двух сотен [x] перестают читать целиком, и живые пункты в нём теряются. Теперь
сделанное удаляется, след остаётся в коммитах и DECISIONS. Второй: план построчно
повторял записи журнала версий канона, то есть был вторым домом для шагов
повышения, и половина повторов протухла молча. Теперь на журнал стоит ссылка.
Новый план — пять разделов: вернуть живые проекты в рабочее состояние, учёт работ
без спринтов, калибровка, пайплайн одной задачи в три этапа, обкатка. Поимённой
раскладки файлов healthlog в нём нет намеренно: её знает canon adopt, и второй
перечень разошёлся бы со скиллом. Зато названо то, чего скилл не сделает и что
легко потерять — гейт проекта теперь три шага вместо одного, потому что docs.py
перестал тянуть за собой и задачи, и форму config.yaml.
REMAINING ссылался на разделы TODO по номерам — переведён на имена; заодно строка
про непрогнанное на живом проекте дополнена скиллом openspec и оговоркой, что
раскол проверен только на фикстурах и на установке каждого плагина в одиночку.
Решение 53: canon и docs остаются двумя скиллами. Довод не про объём, а про
description — это триггер, по которому загрузчик решает, звать ли скилл, и
моменты вызова у этих двух разные. Слитое описание покрывает оба хуже, чем два
покрывают каждое своё.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Замечено при сверке документов канона с составом ступеней: три документа
остались без читателя ниже wide — security.md, database.md и adr/. Проект
поддерживал их, а на 90% задач не открывал никто. Причина оказалась не в
переезде проходов, а в том, как описан состав прогона.
Список тем нигде не был записан: он существовал побочным продуктом списка
проходов. Проход уезжал в верхнюю ступень — и тема уезжала с ним беззвучно.
Отчёт честно говорил «ops не запускался» и не говорил «эксплуатацию не смотрел
никто», а нужно второе. Теперь тема первична, проход вторичен — это правило 0
конвейера, а прогон описывается таблицей «тема → дом → глубина → кто закрывает»,
и таблица есть в каждом отчёте.
Тема есть документ, список открытый. Всё, что проект кладёт в docs/, становится
темой ревью; запретить нельзя, разрешения не надо. Не темы ровно две: docs/tasks/
и docs/review — настройка самого конвейера, слой над темами. Отсюда главное:
docs/ перестал быть документацией и стал конфигурацией конвейера. Проект
настраивает проверку тем, что пишет о себе, а не отдельным файлом настроек,
который разошёлся бы с документами. Ядро — requirements, autotests, conventions,
architecture, security, operations; всё сверх разбирает basics, потому что
именных проходов конечное число, а тем столько, сколько заведёт проект.
Тема живёт файлом или каталогом, на выбор проекта: docs/security.md и
docs/security/ — одно и то же. Прежде форма была задана поимённо и обосновать её
было нечем; заодно в TODO висел вопрос «а если architecture.md разрастётся».
Теперь ответ механический: разросся — стал каталогом с README.md, и это не смена
версии. Обе формы сразу — ошибка, docs.py её ловит.
Заведён review-scope, sonnet, стадия 0, до гейта: находит документы, выводит
темы, назначает глубины, выбирает ступень с обоснованием. Довод оказался сильнее
синхронизации документов — до сих пор профиль называл тот же оркестратор,
который написал код, то есть в точке выбора глубины проверки разведённости с
автором не было вовсе, а решала она под давлением «я почти закончил». Вызывающий
пайплайн профиль больше не передаёт. Поднять и понизить ступень разметчик вправе
одинаково, но обоснование обязательно всегда.
Sonnet ему хватает потому, что вывод устроен как список: каждый файл в docs/
обязан попасть в план темой или строкой «не тема, потому что», и план сверяется с
ls docs/ за секунду. Выбор ступени — суждение, но у него три независимых
корректора: отрицательный тест quick, правило «спорный случай вниз» и сигнал
basics о заниженной ступени.
Разметчик передаёт адреса, а не пересказ. Проект однажды уже держал
review-brief.md и убрал его: второй дом расходится с первым и выглядит
актуальным. Пересказ в задании — тот же посредник, живущий один прогон.
Исключение одно: отсутствие дома, этого проход сам дёшево не выяснит.
quick и standard совпали составом и разошлись глубиной — иначе требование
«нижние ступени закрывают все темы, просто не так глубоко» не выполняется.
Глубин три, и они про способ доказательства, а не про старательность: сверка
(открыть дом, открыть дифф, сравнить), разбор (построить сценарий рассуждением),
доказательство (прогнать, померить, построить путь). Третья есть только в wide.
Цена принята: это единственное место, где профиль не выводится из списка
проходов, поэтому глубина объявляется в отчёте наравне со ступенью.
review-code переписан, и это оказалось крупнее исходной находки: код как код не
читал никто. specs сверял с требованиями, basics — с отказами окружения,
architecture — с устройством, а code был проходом только по прозаическим
конвенциям и прямо объявлял, что рантайм и логика не его. «Здесь ошибка в логике»
не говорил вообще никто. Теперь у прохода две половины: девять классов
технического дефекта (необработанная ветка отказа, пустое и нулевое, граница
диапазона, перепутанный операнд, неосвобождённый ресурс, изменение под итерацией,
неверно применённый интерфейс библиотеки, недостижимая ветка, «сделано соседнее»)
и прежняя сверка с конвенциями. Модель поднята до opus по признаку темы 35: цена
пропущенной находки — дефект в проде.
Канон повышен до версии 5: форма дома на выбор, открытый список тем, AGENTS.md
законно лежит рядом с CLAUDE.md, «Вопросы к проходам» → «Вопросы по темам» (имя
прохода переезд не переживает, тема переживает), «Недоступно проверке» — тоже по
темам. docs.py переписан под темы: ловит двойной дом, принимает обе формы,
перечисляет свои темы проекта вместо «файл вне канона».
Побочно закрыт давний пункт TODO про каталожную форму architecture.md — решать
больше нечего.
Прогон от всего этого стал дороже, а не дешевле, впервые за сессию: плюс scope в
голове каждого прогона, плюс code на opus, плюс basics теперь и в quick. Куплены
разведённость выбора ступени, видимость непокрытых тем и технический разбор кода,
которого не было вовсе.
Тема 36 в DECISIONS.md, следствия 137-140.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Тема 33 сняла самую большую разовую статью расхода, но не тронула главную —
частоту. Меряющая пара стояла в standard, то есть на большинстве задач, и именно
она делала прогон долгим: два прохода держат машину, идут цепочкой и доказывают
находки запуском. Цель разбора названа прямо: лучше поправить в следующей задаче,
чем держать одну два часа.
adversary и ops переехали в wide. Стадия осталась самой урожайной за всю историю
замеров — пять из семи выживших находок дозапуска и единственная находка про
молчаливый старт отката, — но её ценность оплачивается на каждой задаче, а
получается на немногих. Решение по цене, не по ценности.
Заведён review-basics: мелкая осадка двух тяжёлых проходов, без единого запуска.
Стоит только в standard. Восемь вопросов, на которые отвечают чтением: таймаут и
отказ соседа, идемпотентность и одновременная запись, остановка на середине,
частичный откат при двух версиях, наблюдаемость и тишина, очевидный рост объёма,
второй способ мимо единой точки (грепом, не картой), что отсюда удалить. Потолок
4 находки, машину не держит, ничего не меряет.
Вопрос про частичный откат — не для полноты списка. Без него правило «миграция
схемы не поднимает ступень» рассыпалось бы: раньше миграцию разбирал ops, а он
теперь наверху. Проход заведён затем, чтобы у standard остался хоть один взгляд
на ось времени.
Модель у него верхняя, opus, и это не спорит со словом «средний»: усилие режется
входом и потолком, а не моделью. Дешёвая модель на опиниативном проходе платит
триажем — это записанный замер, отменять его без нового замера нечем.
Лестница вышла 4/5/7. Главный выигрыш не в числе проходов, а в том, что из
standard ушла цепочка: теперь там гейт, три прохода одним сообщением и триаж —
граф плоский, ждать некому.
Правило выбора ступени переписано на два вопроса, и объём изменения вошёл в него
впервые. Крупное или незнакомое — трогает несколько узлов, переносит
ответственность, форму решения нащупывают по ходу — это wide, и он рассчитан на
5-10% задач. Мелкое — один узел, форма очевидна заранее, откат сводится к
обратной правке — quick. Всё остальное standard, рабочее умолчание. Раньше
ступень выбиралась только по классу изменения и на размер смотреть запрещала;
теперь признаков два: класс отвечает за обратимость, объём — за цену
разбирательства.
Отрицательный тест сохранил прежнюю мудрость в новой рамке: что после мерджа не
откатывается обратной правкой — не quick, каким бы маленьким ни был дифф. Три
строки миграции идут в standard.
Спорный случай решается вниз, и асимметрия объяснена ценой: ошибка в сторону
standard стоит находки на следующей задаче, ошибка в обратную — трёх тяжёлых
проходов на каждой задаче, выбранной неверно.
Сделка записана вместе с обратной связью, иначе это тихая потеря качества. На
quick и standard не проверяется ничего, что требует запуска: построенный путь,
эксперимент против драйвера, любое число. Это самая крупная граница покрытия
конвейера, и она идёт строкой в каждом таком прогоне поимённо. Сигналов о том,
что ступень занижена, два: журнал дефектов в docs/review.md и сам basics —
он единственный, кто смотрит на дифф целиком на нижних ступенях, и обязан
сказать строкой, если задача выглядит крупнее профиля.
Побочно: условие профиля design то же самое, так что rubric и architecture на
предложении тоже упали до 5-10% задач.
Тема 34 в DECISIONS.md, следствия 130-133. Версия канона не поднята; инструкция
проекту дописана в пункт 8 записи «Версия 4».
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Прогоны стали долгими, а счёт в токенах заметным. Разбор шёл не по находкам, а
по статьям расхода. Две названы прямо: убрать reimpl и убрать fable.
reimpl писал свою реализацию узла, не открывая существующую, и диффил по
решениям. Его счёт определялся объёмом вывода — он один писал код, а не читал
его, — и на прогоне это была самая большая строка. Снят по цене.
Профиль deep от этого не похудел, а исчез: reimpl был единственным, чем он
отличался от wide, и без него у двух имён оказался бы один состав. Ровно от
этой болезни лечилась ступень wide решением JJJ — у профиля обязан быть один
правильный ответ, иначе реестр состава нечем проверять. Ступеней три: quick,
standard, wide.
Вместе с профилем снято всё, что обслуживало только его. Барьер стоимости —
он держал дорогой проход, чтобы тот не писал реализацию против кода, который
через час перепишут; дорогого прохода нет, граф стал плоским во всех профилях,
рёбер осталось два вида вместо трёх. Тест «идентичность, слияние, разбор» —
полторы страницы, служившие единственной цели: выбрать deep не по ощущению;
вместе с ним ушёл проектный перечень мест в docs/review.md и его скелет в
каноне. Стадии перенумерованы: 0 гейт, 1 сверка, 2 враждебный и
эксплуатационный, 3 архитектурный, 4 триаж — дыра на месте третьей читалась бы
как пропущенная стадия.
Снятие записано как сознательное сужение, а не как «класс оказался пустым».
calibration.md требует замера на двух проектах перед удалением прохода; замера
не было, было решение о цене. Поэтому в «Честном пределе» стоит строка: «не
знаю, чего не знаю» больше не достаёт никто. Остаток независимого взгляда дают
профиль design и architecture, но альтернативной реализации, с которой можно
сдиффить решения, у конвейера нет. Класс уходит в границы покрытия каждого
прогона, у проекта — в подраздел «перестали проверять сознательно». Без этой
записи снятие через месяц читается как «проверено и признано лишним».
fable снят с троих: review-triage, review-architecture, doc-code-drift — все на
opus. Основание верхней модели «ошибка распространяется дальше самой находки»
осталось, но оно объясняет, почему двое не опускаются до sonnet, а не почему им
нужна ступень выше opus: разницы в пользу более дорогой модели не показал ни
один прогон, а время и счёт она множила. Палитра схлопнулась до двух цветов,
красного в репозитории больше нет, frontmatter.py теперь отвергнет модель вне
sonnet и opus.
Версия канона не поднята сознательно. Проектам всё равно надо снести перечень
мест для deep из docs/review.md, поэтому пункт вписан в «Что сделать проекту»
записи «Версия 4» — её ещё не гонял ни один проект, оба ждут в TODO.
Тема 33 в DECISIONS.md, следствия 127-129.
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>
В уставе стоял заголовок «Форма записи — только для 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 на выдуманном проекте — консольные крестики-нолики
на 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>
Тема 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>
Тема 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>
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 перестали занижать: коммитов одиннадцать, переписок три
- DECISIONS.md: 29 решений по восьми темам, каждое с причиной; две отменённые
версии сохранены с объяснением отмены
- TODO.md: план в порядке выката, замер блокирует переезд jellybit