Commit Graph
4 Commits
Author SHA1 Message Date
avandClaude Opus 5 a79266cfcb init заводит openspec сам; конфиг стал слотом канона
Каталог openspec/ был предпосылкой, о которой канон говорил, но за которой не
следил. openspec/specs/ объявлен домом темы requirements, config.yaml описан
абзацем — а заводилось всё руками, и не проверялось ничего. Новый проект выходил
из init с полным каноном документов и без каталога, без которого не работают ни
opsx:propose, ни ревью дизайна, ни сверка требований.

Теперь init делает openspec init --tools claude шагом 3, до первого документа, а
adopt заводит его тем же способом, если на переводимом проекте его нет. Команда
названа поимённо в трёх местах — скилле, каноне и отказе docs.py: отказ без
команды заставляет искать её в другом месте.

Файл из коробки оказался хуже отсутствующего, и потому проверяется машиной.
openspec init кладёт config.yaml, где context и rules — закомментированный пример
на английском. Такой файл читается как настроенный: он есть, он валиден, имя
правильное. Работает он как пустой, и узнаётся это по уже написанному
предложению — на другом языке, с capability по имени пакета, без единого SHALL.
docs.py проверяет четыре вещи, каждая про молчащий пробел: каталог есть; имя
именно config.yaml (config.yml OpenSpec не читает и об этом не сообщает); context
и rules.specs не остались примером, а правила называют SHALL; context называет
passport и CLAUDE.md. Последние два обязательны по порядку работы: предложение
пишется до того, как кто-либо откроет docs/, и без этих строк его пишут, не зная
ни границы домена, ни инвариантов.

Форма конфига записана скелетом и сформулирована разрезом: утверждение, которое
можно опровергнуть, открыв другой файл проекта, — пересказ; строка, которая
говорит, какой файл открыть, — ссылка. Машина этот разрез не проверяет, отличить
одно от другого она не умеет; он отдан doc-consistency отдельным абзацем правила
«один факт — один дом», и config.yaml добавлен ему во вход. Место второго дома
там самое частое: context читается при порождении каждого артефакта, туда удобно
дописать «чтобы агент знал», и так заводятся копии инвариантов, конвенций,
состава гейта и правил ревью.

Образец лёг в канон, а не в конвейер, как планировало решение C: форма документа
принадлежит владельцу канона документов, конвейер её читатель. Иначе
av-dev-pipeline завёл бы описание файла, который заводит и проверяет av-dev-pm.

Канон повышен до версии 7 с записью, выполнимой upgrade: завести openspec,
привести config.yaml к скелету, вычистить из context пересказ, проверить имя
файла, поднять номер в .pm.json. Проверка прогнана на четырёх фикстурах — свежий
openspec init, два живых проекта и пустой каталог; отличает все четыре случая.
Решение — 47.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 11:59:01 +03:00
avandClaude Opus 5 4386eb3e1c шов между плагинами: канон перестал называть имена проходов
av-dev-pm и av-dev-pipeline раздельны: канон работает без конвейера, конвейер без
канона — поразрядно деградируя и называя это строкой. Но канон в шести местах
называл конвейер поимённо, и одно из них — вывод docs.py пользователю: «свои темы
проекта: … — их разбирает review-basics». Такая строка чинится не правкой файла,
а недоумением на чужом проекте.

Правило записано в canon.md, чтобы не отрастало заново. Общий словарь — имена тем
и имена ступеней, и только они: ими проект настраивает ревью, вопросами по темам
и триггерами профиля. Имён проходов канон не называет нигде. Направление
несимметрично, и это верно: конвейер называет документы канона поимённо, потому
что он их читатель, а обратной ссылки быть не может — документ живёт дольше, чем
раскладка проходов.

Что вычищено: имя review-basics в canon.md, в changelog версии 5 и в выводе
docs.py; «её берёт basics» из таблицы ролей; описательные адресации того же
класса — «архитектурный проход судит», «враждебный проход выдумает». Худшей была
строка в skeletons.md «там идут враждебный, эксплуатационный и архитектурный
проходы»: утверждение о составе ступени, живущее на стороне, которая о составе не
знает. Строка таблицы «эксплуатационный проход ревью» стала «тема ревью
operations» — заодно совпала со словарём, к которому tasks/SKILL.md отсылает как
к единому дому.

Отдельно — пример, нарушавший собственное правило. Объяснение, почему вопросы
адресуются темам, звучало «вопрос, адресованный ops, перестал задаваться в тот
день, когда ops уехал в верхнюю ступень»: правило про нестабильность имён,
проиллюстрированное именем. Стало «адресованный проходу» и переживёт
переименование.

Починена и висячая ссылка: project-facts.md отсылал к таблице «Кто читает» в
каноне, которой там нет — она была убрана правкой, вводившей темы, и по новому
правилу её и не должно быть. Списка читателей не ведёт никто: читателя назначает
план прогона.

Тема 38 в DECISIONS.md, следствия 143-144.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 08:57:09 +03:00
avandClaude Opus 5 2d39a77444 ревизия покрытия av-dev-pm: три решения из шести оказались «убрать»
Сабагент в роли продакт-менеджера оценил покрытие жизненного цикла личного
проекта скиллами и агентами 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>
2026-08-05 14:02:04 +03:00
avandClaude Opus 5 354a6b03d5 канон 4: слаг подкреплён проверкой, обещанный судья заведён
Оба пункта заметок оказались одним классом: правило записано и никем не
исполняется.

Слаги. 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>
2026-08-05 10:20:39 +03:00