resolve: третий сценарий — обслуживание, у цикла SDD там нет входа
Задача, не меняющая поведения (тулчейн, зависимости, сборка, гит-хуки, перенос, чистка), шла полным циклом решения. Все его шаги стоят на дельта-спеках, а у chore их нет по построению: цикл не урезан ради дешевизны, он остаётся без входа. Признак — связка: тип записи предлагает, отсутствие дельт подтверждает, а расхождение признаков это стоп. Размер признаком не стал намеренно: «мелкое — коротким путём» и есть самая дешёвая лазейка. Планового стопа у сценария нет вовсе — объяснять человеку нечего, выбора там не делают; правило необратимого поэтому действует жёстче, чем в двух других. Ревью идёт фиксированным планом без метки и без разметчика — autotests и operations, плюс conventions с техническим разбором, когда дифф трогает код. Конвейер получил раздел «Прогон без change»: он написан вокруг change, и без этой строки вызов упирался бы в предпосылку OpenSpec. Главный шаг сценария — синк документации, а триггеры ADR работают стоп-признаком: своего источника у обслуживания нет, и решение с ценой уходит в разведку.
This commit is contained in:
@@ -0,0 +1,327 @@
|
||||
# Сценарий «обслуживание»
|
||||
|
||||
Способ решения известен, а **того, что нормирует спека, задача не трогает**:
|
||||
тулчейн и сборка, зависимости, гит-хуки и шаги гейта, перенос и чистка. Сценарий
|
||||
**пишет код**, но не заводит change и не пишет требований. Исход — работающая
|
||||
оснастка и синхронная ей документация.
|
||||
|
||||
Сценарий выбирается развилкой на входе скилла ([SKILL.md](../SKILL.md), раздел
|
||||
«Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его
|
||||
ход; общее для всех трёх сценариев — вход, обращение к соседним плагинам, правило
|
||||
записанного вопроса, правило необратимого — живёт в SKILL.md и тут не
|
||||
пересказывается.
|
||||
|
||||
## Почему цикл SDD здесь не урезан, а не имеет входа
|
||||
|
||||
Это не поблажка по цене, и формулировать её как «мелкая задача — короткий путь»
|
||||
нельзя: путь, выбираемый по самооценке размера, и есть тот самый дешёвый способ
|
||||
«ускориться», против которого написана вся защита сценария решения.
|
||||
|
||||
**У обслуживания нет дельта-спек по построению.** Тип `chore` определён через
|
||||
«наблюдаемое поведение не меняется», а на дельтах стоит весь цикл: `propose`
|
||||
их порождает, разметка выведена **из них**, `review-specs` сверяет **с ними**,
|
||||
объяснение чекпоинта собирается из `proposal.md` и `design.md`, `archive` вливает
|
||||
их в актуальные спеки. Change без дельт — пустой артефакт, который потом надо
|
||||
архивировать, и разметчик по нему назовёт не те темы.
|
||||
|
||||
То есть механика цикла остаётся не пропущенной, а **без входа**. Отсюда и состав
|
||||
сценария: выпали ровно те шаги, у которых нет предмета, и не выпал ни один из
|
||||
тех, у которых он есть.
|
||||
|
||||
## Признак — связка, а не одно условие
|
||||
|
||||
Сценарий выбирается двумя проверками сразу, и обе обязательны:
|
||||
|
||||
1. **тип записи предлагает** — `chore`, реже `fix`, чьё исправление возвращает
|
||||
поведение к уже записанному в спеке;
|
||||
2. **отсутствие дельт подтверждает** — прочитав постановку, ты не находишь
|
||||
требования, которое пришлось бы добавить, изменить или снять.
|
||||
|
||||
Один признак без второго не выбирает сценарий. Тип объявляет автор записи, и он
|
||||
может ошибиться в обе стороны; отсутствие дельт — суждение исполнителя, и оно
|
||||
принимается только тогда, когда согласуется с объявленным типом. Расхождение
|
||||
двух признаков — это не развилка, а стоп: скажи, что тип и предмет работы
|
||||
разошлись, и остановись.
|
||||
|
||||
**Имя сценария не равно имени типа, и это намеренно.** `fix` без дельта-спеки
|
||||
идёт сюда законно — поведение разошлось с **заявленным**, значит заявленное уже
|
||||
записано, и менять спеку не нужно. Сценарий, названный именем типа, такую задачу
|
||||
либо отправил бы в полный цикл ради пустого change, либо принял бы как
|
||||
исключение, а исключения не исполняются.
|
||||
|
||||
## Дельта нашлась по ходу — это стоп
|
||||
|
||||
Признак тот же, что на шаге 7 сценария решения: **меняется ли то, что записано в
|
||||
`openspec/specs/`**. Обнаружилось, что меняется, — работа перестала быть
|
||||
обслуживанием в ту же секунду, и продолжать её нельзя: коммит обслуживания
|
||||
заявляет «поведение не менялось», а оно меняется.
|
||||
|
||||
**Сделанное не выбрасывается.** Оно остаётся в рабочем дереве и уезжает в change
|
||||
следующим прогоном, который идёт сценарием решения. Коммитить его сообщением про
|
||||
обслуживание нельзя: так поведение меняется молча, и ни ревью дизайна, ни
|
||||
чекпоинт по нему уже не пройдут никогда.
|
||||
|
||||
## OpenSpec здесь не предпосылка
|
||||
|
||||
Как и разведке, обслуживанию OpenSpec не нужен: оно не заводит change, не пишет
|
||||
дельта-спек и не архивирует. Ни один из проходов его плана ревью на дельта-спеки
|
||||
не завязан — это сказано и в `av-dev-code:review`, раздел «Прогон без change».
|
||||
Каталога в проекте нет — обслуживание идёт целиком, и деградацией это не
|
||||
является.
|
||||
|
||||
## Планового стопа у этого сценария нет
|
||||
|
||||
**И это следствие, а не упрощение.** Чекпоинт решения объясняет человеку
|
||||
**выбор**: в чём проблема, как решаем, чем рискуем. У обслуживания выбора нет по
|
||||
построению — что делать, сказано в записи, а критерии приёмки у него самые
|
||||
дешёвые из всех типов: команда, которая раньше падала или требовала трёх шагов.
|
||||
Объяснение свелось бы к пересказу задачи её же автору. Стоп, на котором нечего
|
||||
решать, вырождается в обряд одобрения и обесценивает те стопы, где решать есть
|
||||
что.
|
||||
|
||||
**Правило необратимого при этом действует полностью** (SKILL.md, «Когда
|
||||
спрашивать вне чекпоинта»), и здесь оно опаснее, чем кажется. Единственный
|
||||
сценарий без планового стопа — ровно тот, чья работа чаще прочих лезет в
|
||||
выкладку, в токены, в хуки и в чужие данные. Правка оснастки выглядит безобидной
|
||||
до момента, когда её уже не откатить.
|
||||
|
||||
## Ход работы
|
||||
|
||||
```mermaid
|
||||
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. гейт проекта зелёный, и **если правка трогала сам гейт — сверен его состав**,
|
||||
а не только цвет;
|
||||
2. ревью проведено фиксированным планом сценария, исход назван по каждой теме
|
||||
плана, а темы, которых в плане нет, названы в границах покрытия;
|
||||
3. **документация синхронизирована с принуждённым отрицанием** — каждый документ
|
||||
канона получил строку;
|
||||
4. коммит сделан в текущую ветку;
|
||||
5. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван
|
||||
оракул и наблюдаемый исход.** Это доклад приёмщику, а не отметка «принято»:
|
||||
исполнитель и приёмщик здесь совпали, и правило то же, что в решении.
|
||||
|
||||
## Шаги
|
||||
|
||||
### 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](../../review/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, а не после написанного кода.
|
||||
- **Отсутствие чекпоинта не делает сценарий автономнее прочих.** Правило
|
||||
необратимого здесь то же, и срабатывает оно чаще: выкладка, токены, хуки,
|
||||
чужие данные — обычное содержимое задач обслуживания.
|
||||
- **Зелёный гейт после правки гейта ничего не доказывает.** Это единственное
|
||||
место конвейера, где инструмент проверяет сам себя, и потому состав сверяется
|
||||
отдельно от цвета.
|
||||
- **Правка оснастки, сделанная «заодно» внутри чужой задачи, этим сценарием не
|
||||
проходит вовсе** — она едет в чужом коммите и не получает ни своего ревью, ни
|
||||
своей строки синка. Заметил нужную правку по ходу решения — вопрос в запись,
|
||||
а не правка мимоходом.
|
||||
Reference in New Issue
Block a user