Задача, не меняющая поведения (тулчейн, зависимости, сборка, гит-хуки, перенос, чистка), шла полным циклом решения. Все его шаги стоят на дельта-спеках, а у chore их нет по построению: цикл не урезан ради дешевизны, он остаётся без входа. Признак — связка: тип записи предлагает, отсутствие дельт подтверждает, а расхождение признаков это стоп. Размер признаком не стал намеренно: «мелкое — коротким путём» и есть самая дешёвая лазейка. Планового стопа у сценария нет вовсе — объяснять человеку нечего, выбора там не делают; правило необратимого поэтому действует жёстче, чем в двух других. Ревью идёт фиксированным планом без метки и без разметчика — autotests и operations, плюс conventions с техническим разбором, когда дифф трогает код. Конвейер получил раздел «Прогон без change»: он написан вокруг change, и без этой строки вызов упирался бы в предпосылку OpenSpec. Главный шаг сценария — синк документации, а триггеры ADR работают стоп-признаком: своего источника у обслуживания нет, и решение с ценой уходит в разведку.
28 KiB
Сценарий «обслуживание»
Способ решения известен, а того, что нормирует спека, задача не трогает: тулчейн и сборка, зависимости, гит-хуки и шаги гейта, перенос и чистка. Сценарий пишет код, но не заводит change и не пишет требований. Исход — работающая оснастка и синхронная ей документация.
Сценарий выбирается развилкой на входе скилла (SKILL.md, раздел «Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его ход; общее для всех трёх сценариев — вход, обращение к соседним плагинам, правило записанного вопроса, правило необратимого — живёт в SKILL.md и тут не пересказывается.
Почему цикл SDD здесь не урезан, а не имеет входа
Это не поблажка по цене, и формулировать её как «мелкая задача — короткий путь» нельзя: путь, выбираемый по самооценке размера, и есть тот самый дешёвый способ «ускориться», против которого написана вся защита сценария решения.
У обслуживания нет дельта-спек по построению. Тип chore определён через
«наблюдаемое поведение не меняется», а на дельтах стоит весь цикл: propose
их порождает, разметка выведена из них, review-specs сверяет с ними,
объяснение чекпоинта собирается из proposal.md и design.md, archive вливает
их в актуальные спеки. Change без дельт — пустой артефакт, который потом надо
архивировать, и разметчик по нему назовёт не те темы.
То есть механика цикла остаётся не пропущенной, а без входа. Отсюда и состав сценария: выпали ровно те шаги, у которых нет предмета, и не выпал ни один из тех, у которых он есть.
Признак — связка, а не одно условие
Сценарий выбирается двумя проверками сразу, и обе обязательны:
- тип записи предлагает —
chore, режеfix, чьё исправление возвращает поведение к уже записанному в спеке; - отсутствие дельт подтверждает — прочитав постановку, ты не находишь требования, которое пришлось бы добавить, изменить или снять.
Один признак без второго не выбирает сценарий. Тип объявляет автор записи, и он может ошибиться в обе стороны; отсутствие дельт — суждение исполнителя, и оно принимается только тогда, когда согласуется с объявленным типом. Расхождение двух признаков — это не развилка, а стоп: скажи, что тип и предмет работы разошлись, и остановись.
Имя сценария не равно имени типа, и это намеренно. fix без дельта-спеки
идёт сюда законно — поведение разошлось с заявленным, значит заявленное уже
записано, и менять спеку не нужно. Сценарий, названный именем типа, такую задачу
либо отправил бы в полный цикл ради пустого change, либо принял бы как
исключение, а исключения не исполняются.
Дельта нашлась по ходу — это стоп
Признак тот же, что на шаге 7 сценария решения: меняется ли то, что записано в
openspec/specs/. Обнаружилось, что меняется, — работа перестала быть
обслуживанием в ту же секунду, и продолжать её нельзя: коммит обслуживания
заявляет «поведение не менялось», а оно меняется.
Сделанное не выбрасывается. Оно остаётся в рабочем дереве и уезжает в change следующим прогоном, который идёт сценарием решения. Коммитить его сообщением про обслуживание нельзя: так поведение меняется молча, и ни ревью дизайна, ни чекпоинт по нему уже не пройдут никогда.
OpenSpec здесь не предпосылка
Как и разведке, обслуживанию OpenSpec не нужен: оно не заводит change, не пишет
дельта-спек и не архивирует. Ни один из проходов его плана ревью на дельта-спеки
не завязан — это сказано и в av-dev-code:review, раздел «Прогон без change».
Каталога в проекте нет — обслуживание идёт целиком, и деградацией это не
является.
Планового стопа у этого сценария нет
И это следствие, а не упрощение. Чекпоинт решения объясняет человеку выбор: в чём проблема, как решаем, чем рискуем. У обслуживания выбора нет по построению — что делать, сказано в записи, а критерии приёмки у него самые дешёвые из всех типов: команда, которая раньше падала или требовала трёх шагов. Объяснение свелось бы к пересказу задачи её же автору. Стоп, на котором нечего решать, вырождается в обряд одобрения и обесценивает те стопы, где решать есть что.
Правило необратимого при этом действует полностью (SKILL.md, «Когда спрашивать вне чекпоинта»), и здесь оно опаснее, чем кажется. Единственный сценарий без планового стопа — ровно тот, чья работа чаще прочих лезет в выкладку, в токены, в хуки и в чужие данные. Правка оснастки выглядит безобидной до момента, когда её уже не откатить.
Ход работы
flowchart TD
in["сценарий выбран: обслуживание"]
s1["1. прочитать задачу<br/>критерии приёмки и границы"]
s2["2. сделать правку<br/>гейт тронут — сверить состав, не цвет"]
s3["3. гейт проекта до зелёного"]
s4["4. ревью фиксированным планом<br/>av-dev-code:review, без change"]
s5["5. синк документации — av-dev-docs:docs"]
s6["6. коммит работы — av-dev-git:commit"]
s7["7. закрыть задачу — av-dev-tasks:tasks,<br/>вторым коммитом учёта"]
out["исход назван"]
in --> s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> out
s1 -.->|"форма правки неизвестна"| stop1["стоп: нужна разведка"]
s2 -.->|"меняется дельта-спека"| stop2["стоп: идёт решением,<br/>следующим прогоном"]
Схема — сводка: содержание каждого шага в его разделе ниже, и при расхождении прав текст.
Наблюдаемые исходы сценария
Четыре, и каждый обязан быть назван в докладе прямо:
- сделана — определение сделанного выполнено целиком;
- не доведена — с причиной и с записанным вопросом; названо, что именно сделано и до какой границы;
- меняется спека — работа оказалась изменением поведения. Стоп; сделанное остаётся в рабочем дереве и незакоммиченным, дальше идёт сценарий решения следующим прогоном;
- нужна разведка — форма правки неизвестна (мажорное обновление, смена сборщика, переезд гейта на другой инструмент) или сработал триггер ADR: дорогой откат, намеренный отказ от очевидного подхода, пересмотр прежнего решения. Стоп с названной причиной, разведка идёт следующим прогоном.
Последний исход — не редкость, и его стоит ждать. Незнакомое обслуживание это
выбор подхода с ценой и с тем, что становится невозможным, — предмет чекпоинта
вариантов, а не работы без стопа. И там же решение получает законный источник для
ADR: список источников канон закрыл двумя — архивный design.md и записка
разведки, — а обслуживание не производит ни того ни другого.
Определение сделанного
Задача сделана, когда верно всё:
- гейт проекта зелёный, и если правка трогала сам гейт — сверен его состав, а не только цвет;
- ревью проведено фиксированным планом сценария, исход назван по каждой теме плана, а темы, которых в плане нет, названы в границах покрытия;
- документация синхронизирована с принуждённым отрицанием — каждый документ канона получил строку;
- коммит сделан в текущую ветку;
- критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван оракул и наблюдаемый исход. Это доклад приёмщику, а не отметка «принято»: исполнитель и приёмщик здесь совпали, и правило то же, что в решении.
Шаги
1. Прочитать задачу
Прочитай запись. У chore обязательны два раздела, и оба нужны тебе прямо
сейчас: «Затрагивает» — границы, которые у обслуживания часто не в коде
(конфиг и его образцы, версия зависимости, команда сборки, файл CI), и
«Критерии приёмки» — с оракулами.
Здесь же обе проверки признака: тип предлагает, отсутствие дельт подтверждает (раздел «Признак — связка»). И здесь же — проверка на незнакомое: если форма правки не известна до начала, а нащупывается по ходу, объявляй исход нужна разведка и не начинай.
Проверка на «заодно». Обслуживание любит склеиваться в пачку — обновить
зависимости, переписать сборку и убрать мёртвый код одной задачей. Не мерджится
порознь — это несколько задач: объявляй исход не доведена с причиной «задача
не одна» и останавливайся. Нарезкой владеет av-dev-tasks:tasks, а не ты, и
делать её по ходу нельзя — получится один коммит, в котором обновление
зависимости не отделить от чистки.
2. Сделать правку
Код и конфиги — по конвенциям проекта. Правка right-size: чинится названное в записи, а соседнее не золотится по пути.
Гейт правится — сверь состав, а не цвет. Красный, ставший зелёным, виден
сразу; «проверок стало на две меньше, обе зелёные» не видно ничем, а это самая
дорогая из возможных правок оснастки: молча выключено то, чем проверяется всё
остальное. Состав проверок и способ его снять — дело проекта: он объявляет
их семантикой гейта в CLAUDE.md. Снимай исходное состояние до правки, по
тому, как проект это описал.
Проект состав не описал — скажи строкой доклада, что сверен только цвет.
Обходного пути не выдумывай: угаданный состав хуже отсутствующего, потому что
читается как сверенный. Это же строка и повод — предложить проекту дописать слот
в CLAUDE.md.
3. Гейт до зелёного
Прогони гейт и добейся зелёного — он же условие следующего шага: пока гейт красный, опиниативные проходы не запускаются.
Поведенческая верификация здесь другая, чем в решении. Проверяется не новое
поведение, а то, что прежнее не поехало: команда из CLAUDE.md поднимается, шаг
сборки отрабатывает, хук ставится на чистом клоне. Правка, которую нельзя
проверить ничем, кроме «у меня локально работает», называется в докладе строкой.
4. Ревью — план фиксирован сценарием
Вызови Skill av-dev-code:review, дав базу диффа, режим и план сценария.
Change ты не передаёшь — его нет.
Разметчик здесь не зовётся, и это правило, а не пропуск. Обе оси, по которым
он судит, у обслуживания не определены: размер он меряет по proposal.md,
design.md, tasks.md и дельта-спекам, а незнакомость — по форме решения,
которой здесь нет (незнакомое ушло в разведку шагом 1). Разметчик без своего
корпуса вернул бы метку, выведенную из ничего.
Поэтому план у сценария свой и постоянный:
| Тема | Дом | Кто закрывает | Когда |
|---|---|---|---|
autotests |
CLAUDE.md, семантика гейта |
review-autotests |
всегда |
operations |
architecture.*, раздел эксплуатации |
review-basics, глубина «сверка» |
всегда |
conventions + технический разбор |
conventions.* |
review-code |
дифф трогает код, а не только оснастку |
Триаж обязателен, как и на всяком прогоне: он единственный сток и единственный, кто сверяет план с исходом. План на его входе — не формальность: тема, оставшаяся без отчёта, видна только ему.
Условие третьей строки проверяемое, и смотрится оно по диффу, а не по
намерению: обновление зависимости или правка файла CI кода не трогают, чистка и
перенос — трогают. review-code — единственный проход, который вообще говорит
«здесь ошибка в логике», и чистка, прошедшая без него, проверена только на то,
что она собирается.
Границы покрытия называются полностью. Темы requirements и security в
плане нет: у первой нет предмета — дельта-спек не существует, у второй нет
проходчика на этом сценарии. Обе уезжают в доклад строкой. Отчёт, из которого
исчезло «что не смотрел никто», сообщает «проверено», не сообщая, что именно.
Отработка — как в решении: помеченное инлайн чини сам и не логируй, развилка
— вопросом в запись. После правок снова гейт. Отложенные находки собери в секцию
доклада Урожай; задачи из него заводит av-dev-tasks:tasks, не ты.
5. Синк документации — главный шаг этого сценария
Вызови Skill av-dev-docs:docs. Правило то же и такое же жёсткое:
принуждённое отрицание — каждый документ канона либо назван обновлённым, либо
получает «не требуется, потому что…». Нетронутые группируются одной строкой.
Здесь этот шаг весит больше, чем в решении, и вот почему. Обслуживание не
меняет поведения — значит, почти всё, что оно меняет, это документация: команды,
шаги гейта, зависимости поимённо, пути, имя основной ветки, настройки с числовым
значением, место механизации правила. Ровно эти факты doc-code-drift и сверяет
с кодом (перечень закрыт, живёт в каноне) — то есть сценарий, чаще всех прочих
двигающий сверяемые факты, обязан отчитаться по ним раньше всех прочих.
Отдельно один документ, которого нет в перечне тем, а синку он нужен:
conventions.*, раздел «Механизировано» — если правило переехало в линтер, и
тогда его проза из конвенций удаляется, а не остаётся вторым домом.
adr/ этот сценарий не пополняет, и это не пропуск. У ADR закрытый список
источников — архивный design.md либо записка разведки, — и ни того ни другого
обслуживание не производит. Поэтому триггеры ADR здесь работают стоп-признаком,
а не поводом завести запись: сработал дорогой откат, намеренный отказ от
очевидного подхода или пересмотр прежнего решения — сценарий выбран неверно,
объявляй исход нужна разведка и останавливайся. Решение с ценой обязано
пройти чекпоинт вариантов, а не появиться в коммите обслуживания, чей смысл —
«ничего не решали, поменяли оснастку».
Список документов и их триггеров здесь не дублируется — он в чек-листе скилла
av-dev-docs:docs; копия уже однажды разошлась с оригиналом. Плагина в проекте
нет — иди за перечнем в свой reference,
references/project-facts.md конвейера
ревью, добавь adr/ руками и скажи строкой, что синк сделан по перечню
документов, без списка триггеров.
6. Коммит
Коммить в текущую ветку (git rev-parse --abbrev-ref HEAD), сам ветку не
создавай и не переключай, ничего не пушь.
Сообщение — по-русски, скиллом av-dev-git:commit. Вызов не разрешился —
напиши сам и скажи строкой, что форму коммита не сверял никто. Одна задача — один
осмысленный коммит.
7. Закрыть задачу — после коммита, не раньше
Вызови Skill av-dev-tasks:tasks и попроси закрыть задачу как реализованную.
Порядок обязателен: закрытие удаляет файл задачи, и сделанное до коммита оно
оставило бы задачу закрытой без следа работы, если шаг 6 упадёт.
Закрытие тоже коммитится — вторым коммитом, тут же, сообщением про учёт:
закрыта задача <slug>. Плагина нет — ничего не выдумывай: скажи, что учёт
остаётся за владельцем, и назови исход.
Границы: чего обслуживание не делает
- Не меняет поведения. Обнаружилось, что меняет, — стоп с исходом «меняется спека». Это единственная граница сценария, у которой есть проверяемый признак, и она же единственная, которую выгодно нарушить молча.
- Не решает, нужна ли работа. Как и оба соседних сценария: «надо ли» — вопрос человека.
- Не нарезает пачку на задачи. «Обновить зависимости и переписать сборку» —
это
av-dev-tasks:tasksи его правила нарезки. - Не выбирает форму правки, когда она незнакома, и не принимает решений с ценой. Мажорное обновление, смена инструмента, намеренный отказ идут разведкой: там есть чекпоинт вариантов и законный источник для ADR, здесь нет ни того ни другого.
- Не заводит задачи из урожая ревью. Урожай передаётся списком.
Доклад обслуживания
Общее ядро доклада — в SKILL.md; сверх него сценарий обязан назвать:
- что подтвердило признак — тип записи и то, что дельта-спек не нашлось;
- что стало иначе для разработчика — одной фразой, адресуясь ему, а не выдуманному пользователю;
- состав гейта до и после, если правка его трогала; не сверялся — почему;
- по каждому критерию приёмки: оракул и наблюдаемый исход;
Урожай— отложенные находки списком;- строка границ покрытия: план сценария фиксирован,
requirementsиsecurityна этом прогоне не смотрел никто, и разметчик не запускался.
Тонкости сценария
- Самый частый способ соврать этим сценарием — назвать
choreто, что меняет поведение. Тип, оставшийся от первой формулировки, врёт ровно там, где по нему выбирают путь; проверка признака стоит одного чтения записи и делается на шаге 1, а не после написанного кода. - Отсутствие чекпоинта не делает сценарий автономнее прочих. Правило необратимого здесь то же, и срабатывает оно чаще: выкладка, токены, хуки, чужие данные — обычное содержимое задач обслуживания.
- Зелёный гейт после правки гейта ничего не доказывает. Это единственное место конвейера, где инструмент проверяет сам себя, и потому состав сверяется отдельно от цвета.
- Правка оснастки, сделанная «заодно» внутри чужой задачи, этим сценарием не проходит вовсе — она едет в чужом коммите и не получает ни своего ревью, ни своей строки синка. Заметил нужную правку по ходу решения — вопрос в запись, а не правка мимоходом.