Files
dev-skills/av-dev/skills/code-resolve/references/maintain.md
T
av d79f9d2286 хвост: учёт зовёт оркестратор, третий такт идёт и на отказе
Ревью трансформации нашло, что тема 78 спорит сама с собой в четырёх местах.

Учёт был отдан агенту, хотя перечень оркестратора объявлен закрытым, а
границы задания прямо говорят «задач не заводит»: вызов av-dev:task-track
вернулся оркестратору, агенту третьего такта осталось письмо в документы.

Ветка отказа не была покрыта — на ответе «ничего» правка первого такта
уезжала в коммит невычитанной и с непрогнанным гейтом. Теперь третий такт
идёт всякий раз, когда была реплика; не идёт он только тогда, когда реплики
не было вовсе. Дом правила вычитки в doc-sync знает про два захода.

Барьер карты кластеров из сценария «задачи из ревью и аудита» снимается там,
где его уже прошли: список показан человеку и получил ответ. При прямом
вызове и вызове из code-deep-review карта по-прежнему вопрос.

Счёт стопов сведён в таблицу по сценариям; у обслуживания появился второй
заход и одна реплика с поводом «новый запрет или инвариант». Сигнал сверки
считается по архиву change и каталогу задач разом — иначе chore и research
не считались вовсе — и вошёл в возврат агента и в доклады трёх сценариев.
Ось «род правки документа» внесена в перечень осей.

Журнал — тема 80; отложенный старший долг назван в С287.
2026-08-23 19:43:49 +03:00

521 lines
46 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сценарий «обслуживание»
Способ решения известен, а **того, что нормирует спека, задача не трогает**:
тулчейн и сборка, зависимости, гит-хуки и шаги гейта, перенос и чистка. Сценарий
**пишет код**, но не заводит change и не пишет требований. Исход — работающая
оснастка и синхронная ей документация.
Сценарий выбирается развилкой на входе скилла ([SKILL.md](../SKILL.md), раздел
«Развилка: какой сценарий») и называется вслух первой репликой. Здесь только его
ход; общее для всех трёх сценариев — вход, чего может не быть, правило
записанного вопроса, правило необратимого — живёт в SKILL.md и тут не
пересказывается.
## Почему цикл SDD здесь не урезан, а остался без входа
Это не поблажка по цене, и называть сценарий «коротким путём для мелких задач»
нельзя: путь, выбираемый по самооценке размера, и есть тот самый дешёвый способ
«ускориться», против которого написана вся защита сценария решения.
**У обслуживания нет дельта-спек по построению.** Тип `chore` определён через
«наблюдаемое поведение не меняется», а на дельтах стоит весь цикл: `propose`
их порождает, `review-specs` сверяет **с ними**, объяснение чекпоинта собирается
из `proposal.md` и `design.md`, `archive` вливает их в актуальные спеки. Change
без дельт — пустой артефакт, который потом надо архивировать.
Шаги цикла здесь не пропущены — **им нечего обрабатывать**. Отсюда и состав
сценария: выпали ровно те шаги, у которых нет предмета, и не выпал ни один из
тех, у которых он есть.
## Признак — связка, а не одно условие
Сценарий выбирается двумя проверками сразу, и обе обязательны:
1. **тип записи предлагает**`chore`, реже `fix`, чьё исправление возвращает
поведение к уже записанному в спеке;
2. **отсутствие дельт подтверждает** — прочитав постановку, ты не находишь
требования, которое пришлось бы добавить, изменить или снять.
Один признак без второго не выбирает сценарий. Тип объявляет автор записи, и он
может ошибиться в обе стороны; отсутствие дельт — суждение исполнителя, и оно
принимается только тогда, когда согласуется с объявленным типом. Расхождение
двух признаков — это не развилка, а стоп: скажи, что тип и предмет работы
разошлись, и остановись.
**Имя сценария не равно имени типа, и это намеренно.** `fix` без дельта-спеки
идёт сюда законно — поведение разошлось с **заявленным**, значит заявленное уже
записано, и менять спеку не нужно. Сценарий, названный именем типа, такую задачу
либо отправил бы в полный цикл ради пустого change, либо принял бы как
исключение, а исключения не исполняются.
### Постановка текстом — тип называешь ты, и называешь вслух
Первый признак приходит от автора записи; **текст типа не несёт** (SKILL.md,
«Постановка текстом»). Оба признака тогда твои, и связка выродилась бы в одно
суждение — то самое, ради разведения которого она и заведена.
Разведённость здесь восстанавливается местом, а не вторым автором: **тип и
предмет работы называются до начала работы, первой репликой** — «иду
обслуживанием: считаю это `chore`, потому что …; спека не меняется, потому что
…». Человек, написавший текст, читает это раньше первой правки и поправляет
одной фразой. Названный **после** работы тип не признак, а объяснение уже
сделанного: к этому моменту у тебя есть готовый дифф, и он всегда подтверждает
тот тип, под который писался.
Не назвал — признака нет вовсе, и сценарий выбрал сам себя. Это ровно тот
случай, где «самый частый способ соврать этим сценарием» (раздел «Тонкости»)
ничего не стоит: автора, чей тип можно было бы опровергнуть, здесь нет.
## Дельта нашлась по ходу — стоп, и у него свой порядок
Признак тот же, что у отработки ревью в решении (шаг 5): **меняется ли то, что записано в
`openspec/specs/`**. Обнаружилось, что меняется, — работа перестала быть
обслуживанием в ту же секунду, и продолжать её нельзя: коммит обслуживания
заявляет «поведение не менялось», а оно меняется.
**Задача при этом не сломалась — она оказалась шире своего типа.** Поэтому стоп
здесь не «бросить и доложить», а три шага по порядку.
**1. Назови тип, которым задача оказалась.** Разрез тот же, по которому типы и
разведены:
- **`fix`** — поведение расходится с **заявленным**: спека уже описывает верное,
и правка возвращает систему к записанному;
- **`feature`** — снаружи появляется то, чего не было: спеке нужно новое
требование.
Тип называется прямо и с причиной. «Нужно менять спеки» без имени типа
перекладывает классификацию на человека в тот момент, когда весь материал для неё
у тебя.
**2. Объясни человеку простым языком.** Экран текста, не больше:
- **что просили сделать** — одной фразой из записи;
- **что нашлось** — какое поведение меняется, словами домена, а не именами
файлов и функций;
- **почему это перестало быть обслуживанием** — одной фразой: у обслуживания
поведение не меняется по определению;
- **чем задача становится** — `fix` или `feature`, с причиной из разреза выше;
- **что уже сделано** и что из этого лежит в рабочем дереве.
Проверка на простой язык — общая у трёх сценариев:
<!-- копия: чекпоинт-простой-язык из av-dev/skills/code-resolve/references/solve.md -->
**в тексте нет `SHALL`, нет имён файлов и функций там, где вещь называется
по-русски, и нет слов, которых нет в паспорте проекта.**
<!-- /копия: чекпоинт-простой-язык -->
**3. Дай два решения и жди ответа.** Их ровно два, и оба законны:
- **переформулировать запись** — тип меняется на названный, и дальше задача идёт
**процессом своего типа**: сценарием решения, следующим прогоном. Формат записи
правит `av-dev:task-track`, а не ты: у нового типа своя схема разделов, и
готовность её проверит `ready` — той же машиной, что и на входе. Прогон
обслуживания на этом кончается, исход — «меняется спека».
**Постановка пришла текстом — переформулировать нечего:** человек либо
запускает следующий прогон тем же текстом, и он пойдёт решением, либо заводит
запись через `av-dev:task-track`, если работа должна пережить разговор. Выбор
между этими двумя — его, не твой: заводить запись сам этот скилл не вправе;
- **прекратить работу** — человек не готов расширять задачу сейчас. Исход тот
же, запись остаётся как была, вопрос записывается там, где проект держит
вопросы.
**Третьего решения — «доделать как обслуживание» — нет.** Оно и есть то самое
молчаливое изменение поведения, против которого стоит весь разрез: под коммитом,
заявляющим «поменяли оснастку», уехала бы правка, не прошедшая ни чекпоинта, ни
ревью цикла задачи, и не оставившая следа в спеках.
**Сделанное не выбрасывается ни при каком из двух решений.** Оно остаётся в
рабочем дереве незакоммиченным: при переформулировке уезжает в change следующим
прогоном, при отказе — человек решает сам, откатить или оставить. Коммитить его
сообщением про обслуживание нельзя.
**Прогон, дошедший до этого стопа, стоит дороже обычного** — и это довод за
проверку признака на шаге 1, а не после написанного кода.
## OpenSpec здесь не предпосылка
Как и разведке, обслуживанию OpenSpec не нужен: оно не заводит change, не пишет
дельта-спек и не архивирует. Ни один из проходов его плана ревью на дельта-спеки
не завязан — это сказано и в `av-dev:code-review`, раздел «Прогон без change».
Каталога в проекте нет — обслуживание идёт целиком, и деградацией это не
является.
## Планового стопа у этого сценария нет
**И это следствие, а не упрощение.** Чекпоинт решения объясняет человеку
**выбор**: в чём проблема, как решаем, чем рискуем. У обслуживания выбора нет по
построению — что делать, сказано в записи, а критерии приёмки у него самые
дешёвые из всех типов: команда, которая раньше падала или требовала трёх шагов.
Объяснение свелось бы к пересказу задачи её же автору. Стоп, на котором нечего
решать, вырождается в обряд одобрения и обесценивает те стопы, где решать есть
что.
**Мест, где ответа всё же ждут, два, и через оба проходят не все прогоны.**
Первое — стоп по найденной дельте (раздел «Дельта нашлась по ходу»), и плановым
он не является: через него идут те прогоны, где задача оказалась не тем, чем
объявлена. Второе — **реплика о новом на шаге 5**, и она случается, только если
обслуживание завело в документах что-то, чего не было: запрет или инвариант.
Обычный прогон обслуживания не проходит ни через одно из двух.
**Правило необратимого при этом действует полностью** (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:doc-sync"]
s6["6. коммит работы — av-dev-git:commit"]
s7["7. закрыть задачу — av-dev:task-track,<br/>вторым коммитом учёта"]
out["исход назван"]
in --> s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> out
s1 -.->|"форма правки неизвестна"| stop1["стоп: нужна разведка"]
s2 -.->|"нашлась дельта-спека"| stop2["стоп: назвать тип,<br/>объяснить, дать два решения"]
```
Схема — **сводка**: содержание каждого шага в его разделе ниже, и при расхождении
прав текст.
## Наблюдаемые исходы сценария
Четыре, и каждый обязан быть назван в докладе прямо:
- **сделана** — определение сделанного выполнено целиком;
- **не доведена** — с причиной и с записанным вопросом; названо, что именно
сделано и до какой границы;
- **меняется спека** — работа оказалась шире своего типа. Стоп с объяснением и
двумя решениями человека: переформулировать запись в `fix` или `feature` и
решать её процессом того типа следующим прогоном — либо прекратить. Сделанное
остаётся в рабочем дереве незакоммиченным. Доклад называет **оба**: какой тип
предложен и что человек выбрал;
- **нужна разведка** — форма правки неизвестна (мажорное обновление, смена
сборщика, переезд гейта на другой инструмент) **или сработал триггер ADR**.
Перечень триггеров не пересказывается: он живёт в
[canon.md](../../canon/references/canon.md#adr), и здесь он работает
стоп-признаком — то есть от его точности зависит выбор сценария, а пересказ
расходится с домом молча. Стоп с названной причиной, разведка идёт следующим
прогоном.
**Последний исход — не редкость, и его стоит ждать.** Незнакомое обслуживание —
это выбор подхода с ценой и с тем, что становится невозможным, — предмет чекпоинта
вариантов, а не работы без стопа. И там же решение получает законный источник для
ADR: список источников канон закрыл двумя — архивный `design.md` и записка
разведки, — а обслуживание не производит ни того ни другого.
## Определение сделанного
Задача сделана, когда верно всё:
1. гейт проекта зелёный, и **если правка трогала сам гейт — сверен его состав**,
а не только цвет;
2. ревью проведено фиксированным планом сценария, исход назван по каждой теме
плана, а темы, которых в плане нет, названы в границах покрытия;
3. **документация синхронизирована с принуждённым отрицанием** — каждый документ
канона получил строку;
4. коммит сделан в текущую ветку;
5. **критерии приёмки, если проект их дал, выписаны поимённо, и по каждому назван
оракул и наблюдаемый исход.** Это доклад приёмщику, а не отметка «принято»:
исполнитель и приёмщик здесь совпали, и правило то же, что в решении.
## Шаги
### 1. Прочитать задачу
Прочитай запись. У `chore` обязательны два раздела, и оба нужны тебе прямо
сейчас: **«Затрагивает»** — границы, которые у обслуживания часто не в коде
(конфиг и его образцы, версия зависимости, команда сборки, файл CI), и
**«Критерии приёмки»** — с оракулами.
**Постановка пришла текстом — этих двух разделов нет, и оба нужны тебе тем же
составом.** Границы назови сам и покажи в первой реплике, вместе с типом:
обслуживание чаще прочих сценариев расползается, а границы у него лежат не в
коде, и невидимая граница расползание не удержит. Критериев приёмки в тексте
может не быть вовсе — тогда скажи строкой, что их нет и приёмка идёт по докладу.
Сочинить их себе здесь нельзя даже так, как это делает решение: чекпоинта, на
котором человек их утвердит, у обслуживания нет.
Здесь же обе проверки признака: тип предлагает, отсутствие дельт подтверждает
(раздел «Признак — связка»); постановка текстом типа не объявляла — тогда
называешь его ты, и вслух (раздел «Постановка текстом»). И здесь же — проверка
на незнакомое: если форма правки не известна до начала, а нащупывается по ходу,
объявляй исход **нужна разведка** и не начинай.
**Проверка на «заодно».** Обслуживание любит склеиваться в пачку — обновить
зависимости, переписать сборку и убрать мёртвый код одной задачей. Не мерджится
порознь — это несколько задач: объявляй исход **не доведена** с причиной «задача
не одна» и останавливайся. Нарезкой владеет `av-dev:task-track`, а не ты, и
делать её по ходу нельзя — получится один коммит, в котором обновление
зависимости не отделить от чистки.
### 2. Сделать правку
**Правку делает агент** (SKILL.md, «Кто пишет: письмо уходит агентам»): задание
несёт постановку, конвенции проекта, границы правки и требование довести гейт до
зелёного; возврат — адреса тронутого и исход гейта. Код и конфиги — по конвенциям
проекта. Правка по размеру задачи: чинится названное в записи, соседнее не
улучшается заодно.
**Гейта ещё нет — сказать это, а не изображать сверку.** Первые шаги плана
стройки заводят гейт, сборку и хуки: у них нет ни «до», ни «прежнего», и
определение сделанного через зелёный гейт на них не выполнимо буквально. Такая
задача сделана, когда **заведённое работает на чистом клоне** и это показано в
докладе; пункты 1 и 3 определения ниже закрываются строкой «заводится впервые,
сверять не с чем». Изображать сверку с несуществующим прежним состоянием нельзя —
это ровно то враньё, против которого весь абзац ниже и написан.
**Гейт правится — сверь состав, а не цвет.** Красный, ставший зелёным, виден
сразу; убыли проверок гейт не покажет — он зелёный и до, и после. Это самая
дорогая из возможных правок оснастки: молча выключено то, чем проверяется всё
остальное. Состав проверок и способ его снять — **дело проекта**: он объявляет
их семантикой гейта в `CLAUDE.md`. Снимай исходное состояние **до** правки, по
тому, как проект это описал.
**Исходный состав снимаешь ты, а не агент, и это не мелочь.** Сверка «до и
после» уезжает в твой доклад, а снятое тем же, кто правил, сверкой не является:
агент вернёт состав, который получился, и назовёт его исходным. Снимок делается
до того, как задание ушло.
**Проект состав не описал — скажи строкой доклада, что сверен только цвет.**
Обходного пути не выдумывай: угаданный состав хуже отсутствующего, потому что
читается как сверенный. Это же строка и повод — предложить проекту дописать слот
в `CLAUDE.md`.
### 3. Гейт до зелёного
Прогони гейт и добейся зелёного — он же условие следующего шага: пока гейт
красный, проходы с мнением не запускаются.
**Сразу после зелёного сними отпечаток дерева** (`av-dev:code-review`, ступень 1)
и сохрани его вместе со сводкой и путём к логам шагов. Шаг 4 передаёт их ревью, и
тогда ступень автотестов не гоняет тот же гейт второй раз.
**Поведенческая верификация здесь другая, чем в решении.** Проверяется не новое
поведение, а то, что прежнее не поехало: команда из `CLAUDE.md` поднимается, шаг
сборки отрабатывает, хук ставится на чистом клоне. **У оснастки, заводимой
впервые, прежнего нет** — тогда проверяется, что заведённое работает на чистом
клоне, и в докладе это называется своим именем, а не «регрессий не найдено». Правка, которую нельзя
проверить ничем, кроме «у меня локально работает», называется в докладе строкой.
### 4. Ревью — план фиксирован сценарием
Вызови Skill **`av-dev:code-review`**, дав базу диффа, режим, **план сценария** и
**исход гейта с шага 3** — сводку, путь к логам шагов и отпечаток дерева. Change
ты не передаёшь — его нет.
**План у сценария свой, и он не совпадает с перечнем тем цикла задачи.** Тема
`requirements` там есть, а здесь её предмета нет вовсе; `operations` в цикле
закрыта сверкой с инвариантами внутри `review-code`, а здесь её берёт `basics`
правка оснастки задевает выкладку, откат и соседей чаще, чем что-либо ещё, и
инвариантов на этот счёт у проекта обычно нет.
<!-- дом: план-обслуживания -->
| Тема | Дом | Кто закрывает | Глубина и вход | Когда |
| --- | --- | --- | --- | --- |
| `autotests` | `CLAUDE.md`, семантика гейта | `review-autotests` | как обычно: гейт запускается целиком | всегда |
| `operations` | `architecture.*`, раздел эксплуатации | `review-basics` | **сверка**: дом темы против диффа, потолок 2 | всегда |
| `conventions` + технический разбор | `conventions.*` | `review-code` | как в цикле: дом конвенций целиком, потолок 4 конвенционных, у техники потолка нет; сверка с инвариантами `CLAUDE.md` по темам `security`, `operations`, `architecture`, потолок 1 | дифф трогает код, а не только оснастку |
<!-- /дом: план-обслуживания -->
**Глубина названа в плане потому, что иначе её неоткуда взять.** У `review-basics`
и тема, и глубина приходят заданием — в цикле он держит только свои темы проекта,
а здесь ему дают чужую; без строки плана он взял бы её наугад, то есть по-разному
от прогона к прогону и молча.
**`review-code` идёт тем же составом, что в цикле, и это не совпадение.** Обе его
половины и сверка с инвариантами постоянны — от прогона они не зависят, потому и
переносятся сюда без оговорок. Единственное, что план решает за него, — идти ли
вообще: правка, тронувшая только оснастку, кода не меняла.
Триаж обязателен, как и на всяком прогоне: он единственный сток и единственный,
кто сверяет план с исходом. На его вход подаётся этот план — вместо перечня тем
цикла задачи.
**Условие третьей строки проверяемое, и смотрится оно по диффу**, а не по
намерению: обновление зависимости или правка файла CI кода не трогают, чистка и
перенос — трогают. `review-code` — единственный проход, который вообще говорит
«здесь ошибка в логике», и чистка, прошедшая без него, проверена только на то,
что она собирается.
**Сигнал «просит глубокого ревью» работает и здесь**, но читается иначе: у
обслуживания поднимать нечего — состав фиксирован сценарием. Показалось, что
глубины мало, потому что задача крупнее заявленного, — ищи дельту, а не глубину;
всё прочее уходит строкой «отложено в `av-dev:code-deep-review`».
**Границы покрытия называются полностью:**
- `requirements` — предмета нет, дельта-спек не существует;
- `security` — своего прохода нет; сверена против записанных инвариантов внутри
`review-code`, а он шёл не всегда. Не шёл — тему не смотрел никто, и это
говорится прямо;
- `architecture` — то же: только против инвариантов, и только если шёл `code`.
Отчёт, из которого исчезло «что не смотрел никто», сообщает «проверено», не
сообщая, что именно.
Отработка — как в решении: помеченное `инлайн` чинит **агент** (SKILL.md, «Кто
пишет»), находки уходят ему дословно с оракулом, гейт после правок гоняет он же,
логировать их не надо; `развилка` — вопросом в запись, и агенту она не отдаётся.
Отложенные находки собери в секцию доклада `Урожай`.
**Задачи из урожая — по слову человека, и спрашивается это репликой шага 5**,
вместе с новым в документах: правило общее для всех прогонов конвейера
(`av-dev:code-review`, «Что происходит с находками дальше»), и обслуживание не
исключение. Сказал «заводим» — зовёшь `av-dev:task-track` сам, сценарий «задачи
из ревью и аудита»; не сказал — урожай остаётся строками доклада.
### 5. Синк документации — главный шаг этого сценария, и делает его агент
**Синк уходит агенту** (SKILL.md, «Кто пишет»): работа письменная и нормирована
чек-листом скилла `av-dev:doc-sync`, а не суждением оркестратора. В задании —
корень проекта, база диффа, что было тронуто правкой, требование принуждённого
отрицания и требование довести гейт до зелёного после правок. Вычитку языка
`av-dev:doc-sync` зовёт сам.
**Правило то же и такое же жёсткое: принуждённое отрицание** — каждый документ
канона либо назван обновлённым, либо получает «не требуется, потому что…».
Нетронутые группируются одной строкой. Возврат приходит в этой же форме и уезжает
в доклад целиком: тронутое без нетронутого не отличается от невыполненного шага.
**Второе правило синка тоже действует: отражение пишется молча, новое
предлагается** (дом — раздел «Два рода правок» скилла `av-dev:doc-sync`). Здесь
оно почти ничего не стоит: обслуживание двигает **факты** — команды, шаги гейта,
зависимости поимённо, пути, имя ветки, числа настроек, — а факт в документе,
разошедшийся с кодом, это отражение по определению.
**Повод для реплики у этого сценария один — новый запрет или инвариант в
`CLAUDE.md`**: он свяжет все будущие задачи, и заводить его молча нельзя.
Сужение проверок в `review.*` поводом не является, хотя тоже новое: проверки
сузил человек, и слово по ним уже сказано (`av-dev:doc-sync`, «Два рода правок»).
К этому же поводу примыкает урожай ревью с шага 4 — спрашиваются они одной
репликой, а не двумя.
**Нового нет — реплики нет**, и шаг кончается возвратом агента; так идёт
большинство прогонов обслуживания.
**Реплика была — идёт второй заход тем же агентом**, и на нём висит то же, что в
решении: письмо одобренного, вычитка `doc-wording` по всей пачке и гейт до
зелёного. Первый заход снимает их с себя ровно тогда, когда вернул непустой
список предложений, — порядок и его довод описаны в [solve.md](solve.md), шаг 6.
Задачи из урожая при этом заводишь **ты сам** вызовом `av-dev:task-track`, а не
агент: индексы учёта правит тот, кто коммитит.
**Здесь этот шаг весит больше, чем в решении, и вот почему.** Обслуживание не
меняет поведения — значит, почти всё, что оно меняет, это документация: команды,
шаги гейта, зависимости поимённо, пути, имя основной ветки, настройки с числовым
значением, место механизации правила. Ровно эти факты `doc-code-drift` и сверяет
с кодом (перечень закрыт, живёт в каноне) — то есть сценарий, чаще всех прочих
двигающий сверяемые факты, обязан отчитаться по ним раньше всех прочих.
Отдельно один документ, которого нет в перечне тем, а синку он нужен:
**`conventions.*`, раздел «Механизировано»** — если правило переехало в линтер, и
тогда его проза из конвенций **удаляется**, а не остаётся вторым домом.
**`adr/` этот сценарий не пополняет, и это не пропуск.** У ADR закрытый список
источников — архивный `design.md` либо записка разведки, — и ни того ни другого
обслуживание не производит. Поэтому триггеры ADR здесь работают **стоп-признаком,
а не поводом завести запись**: сработал любой из них — сценарий выбран неверно,
объявляй исход **нужна разведка** и останавливайся. Перечень триггеров — в
[canon.md](../../canon/references/canon.md#adr) и здесь не пересказывается. Решение с ценой обязано
пройти чекпоинт вариантов, а не появиться в коммите обслуживания, чей смысл —
«ничего не решали, поменяли оснастку».
Список документов и их триггеров здесь не дублируется — он в чек-листе скилла
`av-dev:doc-sync`; копия уже однажды разошлась с оригиналом. Документов канона в
проекте нет — синка нет вовсе: скажи это исходом и предложи завести канон
скиллом `av-dev:canon`.
### 6. Коммит
Коммить **в текущую ветку** (`git rev-parse --abbrev-ref HEAD`), сам ветку не
создавай и не переключай, ничего не пушь.
Сообщение — по-русски, **скиллом `av-dev-git:commit`**. Вызов не разрешился —
напиши сам и скажи строкой, что форму коммита не сверял никто. Одна задача — один
осмысленный коммит.
### 7. Закрыть задачу — после коммита, не раньше
**Вызови Skill `av-dev:task-track`** и попроси закрыть задачу как реализованную.
Порядок обязателен: закрытие удаляет файл задачи, и сделанное до коммита оно
оставило бы задачу закрытой без следа работы, если шаг 6 упадёт.
**Закрытие тоже коммитится — вторым коммитом, тут же**, сообщением про учёт:
`закрыта задача <slug>`. Каталога задач в проекте нет — ничего не выдумывай:
скажи, что учёт остаётся за владельцем, и назови исход.
**Постановка пришла текстом — шага нет вовсе**: записи не было, закрывать нечего,
след работы — коммит шага 6. Заводить запись задним числом ради закрытия нельзя.
## Границы: чего обслуживание не делает
- **Не меняет поведения.** Обнаружилось, что меняет, — стоп с исходом «меняется
спека»: назвать тип, объяснить, дать два решения. Это единственная граница
сценария, у которой есть проверяемый признак, и она же единственная, которую
выгодно нарушить молча.
- **Не переписывает запись задачи сам.** Тип ты **предлагаешь** с причиной,
меняет его `av-dev:task-track` и только после ответа человека: исполнитель,
переклеивший тип на ходу, назначает себе другой процесс и другую глубину
проверки.
- **Не решает, нужна ли работа.** Как и оба соседних сценария: «надо ли» —
вопрос человека.
- **Не нарезает пачку на задачи.** «Обновить зависимости и переписать сборку» —
это `av-dev:task-track` и его правила нарезки.
- **Не выбирает форму правки, когда она незнакома, и не принимает решений с
ценой.** Мажорное обновление, смена инструмента, намеренный отказ идут
разведкой: там есть чекпоинт вариантов и законный источник для ADR, здесь нет
ни того ни другого.
- **Не заводит задачи из урожая ревью.** Урожай передаётся списком.
## Доклад обслуживания
Общее ядро доклада — в SKILL.md; сверх него сценарий обязан назвать:
- **что подтвердило признак** — тип записи и то, что дельта-спек не нашлось;
постановка пришла текстом — **тип назвал ты**, и это говорится прямо, вместе с
границами, которые ты объявил себе сам;
дельта нашлась — **какой тип предложен, с причиной, и что человек выбрал**:
переформулировать или прекратить;
- **что стало иначе для разработчика** — одной фразой, адресуясь ему, а не
выдуманному пользователю;
- **состав гейта до и после**, если правка его трогала; не сверялся — почему;
- по каждому критерию приёмки: **оракул и наблюдаемый исход**;
- **`Урожай`** — отложенные находки списком и **что человек по нему решил**;
- **что заведено нового в документах** и что предложено и отвергнуто — по именам
записей; отказ виден только здесь;
- **сигнал сверки** — строка синка о том, сколько задач сделано с прошлого
прогона `av-dev:doc-healthcheck`, либо что сверки не было ни разу;
- **строка границ покрытия**: план сценария фиксирован; темы `requirements` в нём
нет — её не смотрел никто, а `security` и `architecture` смотрелись только
против записанных инвариантов, и то если шёл проход `code`.
## Тонкости сценария
- **Самый частый способ соврать этим сценарием — назвать `chore` то, что меняет
поведение.** Тип, оставшийся от первой формулировки, врёт ровно там, где по
нему выбирают путь; проверка признака стоит одного чтения записи и делается на
шаге 1, а не после написанного кода.
- **Отсутствие чекпоинта не делает сценарий автономнее прочих.** Правило
необратимого здесь то же, и срабатывает оно чаще: выкладка, токены, хуки,
чужие данные — обычное содержимое задач обслуживания.
- **Зелёный гейт после правки гейта ничего не доказывает.** Это единственное
место конвейера, где инструмент проверяет сам себя, и потому состав сверяется
отдельно от цвета.
- **Правка оснастки, сделанная «заодно» внутри чужой задачи, этим сценарием не
проходит вовсе** — она едет в чужом коммите и не получает ни своего ревью, ни
своей строки синка. Заметил нужную правку по ходу решения — вопрос в запись,
а не правка мимоходом.