конфиг: одна версия и один служебный файл, .av-dev.toml в корне
Версий было две — канон 14 в docs/.docs.json и формат задач 1 в <каталог задач>/.tasks.json, — и порознь они двигались потому, что плагины ставились порознь. Плагин один, версия одна и начинается с 1; журналы обеих прежних нумераций закрыты и лежат рядом непереписанными, действующий журнал открывается записью о слиянии с перечнем шагов проекту. Формат TOML взят ради комментариев: файл живёт в репозитории проекта, и назначение числа читают из него самого. Отсюда правило записи — скрипты правят строку, а не переписывают файл. Читатель общий, shared/config.py: два разбора одной схемы были бы двумя домами. Каталог задач перестал узнаваться служебным файлом и называется ключом [tasks] dir; узнают его по индексу. Прежние файлы не читаются — увидев их, docs.py и tasks.py называют прежнюю раскладку и зовут upgrade.
This commit is contained in:
@@ -45,8 +45,9 @@
|
||||
CLAUDE.md памятка агенту: что это, стек, инварианты с
|
||||
severity, команды, семантика гейта, запреты
|
||||
AGENTS.md необязателен, лежит рядом; читается теми же
|
||||
.av-dev.toml версия раскладки и настройки проверок; лежит
|
||||
в корне, потому что нужен и без docs/
|
||||
docs/
|
||||
.docs.json версия канона и пути, нужные проверкам
|
||||
passport.md | passport/ зачем и для кого; чем НЕ является; сценарии
|
||||
architecture.md | architecture/ как сложено — обзор; окружение и эксплуатация
|
||||
database.md | database/ схема хранилища; представление данных и настройки
|
||||
@@ -100,7 +101,7 @@ openspec/
|
||||
| `review.*` | процессный | — (настройка самого конвейера, слой **над** темами) |
|
||||
| `adr.*` | процессный | — |
|
||||
| `research.*` | процессный | — |
|
||||
| `.docs.json` | процессный | — (служебный файл, не документ) |
|
||||
| `.av-dev.toml` | процессный | — (служебный файл, не документ) |
|
||||
|
||||
**Список тем открытый, и это не послабление, а механизм.** Категории
|
||||
`источник` и `процессный` **закрыты** — они перечислены здесь поимённо и
|
||||
@@ -343,10 +344,10 @@ kebab-case.** Причина не эстетическая: имя файла с
|
||||
|
||||
### `tasks/`
|
||||
|
||||
**Каталог задач канону не принадлежит.** Его ведёт отдельный плагин
|
||||
`av-dev-tasks` — своим скриптом, своим конфигом `<каталог>/.tasks.json`, своей
|
||||
версией формата в нём же и своим журналом версий. Канон о том числе не
|
||||
высказывается и его не двигает: повышает каталог задач тот, кто его ведёт.
|
||||
**Каталог задач канону не принадлежит.** Его ведёт скилл `task-track` — своим
|
||||
скриптом и своими проверками; где каталог лежит и как названы его части, говорит
|
||||
секция `[tasks]` в `.av-dev.toml`. Версия там одна на всю раскладку: канон и
|
||||
каталог задач двигаются вместе, потому что двигает их один плагин.
|
||||
Канон **резервирует место** в `docs/` и внутрь не смотрит:
|
||||
`docs.py` каталог не открывает, его отсутствия не считает дрейфом и согласованность
|
||||
задач не проверяет. Проект, поставивший только канон документов, задач не ведёт
|
||||
@@ -538,39 +539,41 @@ kebab-case.** Причина не эстетическая: имя файла с
|
||||
архитектуру с кодом» задача без дна, и агент, которому её поставили, выдаёт
|
||||
правдоподобную труху вместо находок.
|
||||
|
||||
## `docs/.docs.json`
|
||||
## `.av-dev.toml`
|
||||
|
||||
```json
|
||||
{
|
||||
"canon": <текущая версия>,
|
||||
"migrations": "internal/store/migrations"
|
||||
}
|
||||
```toml
|
||||
# Раскладка av-dev в этом проекте: версия и настройки проверок.
|
||||
|
||||
version = 1 # версия раскладки
|
||||
|
||||
[docs]
|
||||
migrations = "internal/store/migrations" # если БД есть
|
||||
|
||||
[tasks]
|
||||
dir = "tasks" # каталог задач от корня репозитория
|
||||
```
|
||||
|
||||
`canon` — версия канона, под которую проект приведён, целым числом: обратной
|
||||
совместимости у канона нет, есть «приведён» и «не приведён». Число подставляет
|
||||
`version` — версия раскладки, под которую проект приведён, целым числом:
|
||||
обратной совместимости нет, есть «приведён» и «не приведён». Число подставляет
|
||||
`init`, `adopt` или `upgrade`, и берётся оно из `docs.py version`, а не из
|
||||
образца: литерал в образце протухает на первом же повышении канона.
|
||||
`migrations` — путь каталога миграций, если БД есть; по нему `docs.py` делает
|
||||
сверку с `database.md`.
|
||||
образца: литерал в образце протухает на первом же повышении.
|
||||
`[docs] migrations` — путь каталога миграций, если БД есть; по нему `docs.py`
|
||||
делает сверку с `database.md`. `[tasks]` — где лежит каталог задач и как названы
|
||||
его части; состав ключей описывает скилл `task-track`.
|
||||
|
||||
**Имя файла — имя плагина, который его завёл.** Канон документов ведёт
|
||||
`av-dev-docs`, поэтому `.docs.json`; у каталога задач по тому же правилу
|
||||
`.tasks.json`, у конвейера — `openspec/config.yaml`. До версии 13 файл звался
|
||||
`.pm.json` — по плагину `av-dev-pm`, который распался на четыре и которого
|
||||
больше нет; имя пережило владельца и указывало в пустоту. Прежнее имя `docs.py`
|
||||
не читает: два дома для одной версии канона расходятся молча, а переименование
|
||||
стоит одну команду (версия 13 журнала, и `check` называет её сам, когда видит
|
||||
старый файл).
|
||||
**Формат TOML взят ради комментариев.** Файл лежит в репозитории проекта, и
|
||||
человек, открывший его через полгода, обязан прочитать в нём, что означает
|
||||
число. JSON комментариев не знает, и объяснение приходилось держать в другом
|
||||
файле. Отсюда же правило записи: скрипты правят **строку**, а не переписывают
|
||||
файл — перезапись стёрла бы то, ради чего формат и выбран.
|
||||
|
||||
**Ключа `tasks` здесь больше нет.** Настройки каталога задач вернулись в свой
|
||||
файл `<каталог задач>/.tasks.json`, потому что ведёт их другой плагин: конфиг,
|
||||
лежащий в `docs/`, был бы домом, которого нет у проекта, поставившего учёт работ
|
||||
без канона документов. Состав ключей описывает тот плагин, а не канон. Там же —
|
||||
**версия формата задач**, и она своя: у проекта без `docs/` версии канона нет
|
||||
вовсе, сверять её было бы не с чем. Прежний ключ читается, пока живы
|
||||
непереехавшие проекты, и `tasks.py` говорит о нём замечанием на каждом
|
||||
прогоне — версия 8 журнала просит его убрать.
|
||||
**Файл один, и лежит он в корне.** До слияния плагинов их было два —
|
||||
`docs/.docs.json` с версией канона и `<каталог задач>/.tasks.json` с версией
|
||||
формата задач, — и версии двигались порознь, потому что плагины ставились
|
||||
порознь. Плагин теперь один, версия одна, а корень выбран потому, что он есть и
|
||||
у проекта без `docs/`, и у проекта без каталога задач. Прежние имена не
|
||||
читаются: два дома для одной версии расходятся молча. Увидев их, `docs.py` и
|
||||
`tasks.py` говорят «прежняя раскладка» и зовут `upgrade` — версия 1 журнала.
|
||||
|
||||
Ключей будет больше по мере роста проверок; неизвестный ключ `docs.py`
|
||||
игнорирует, отсутствующий — считает «проверка неприменима» и говорит об этом
|
||||
|
||||
@@ -0,0 +1,784 @@
|
||||
# Журнал версий канона до слияния плагинов
|
||||
|
||||
**Журнал закрыт.** Он описывает версии канона документов 1–14 — время, когда
|
||||
плагинов было три и у канона была своя нумерация. Действующий журнал —
|
||||
[changelog.md](changelog.md), и его версия 1 идёт **после** записи 14 отсюда.
|
||||
|
||||
Записи не переписаны под нынешние имена: адрес и имя скилла, верные на день
|
||||
записи, остаются там как свидетельство. Записи ниже версии 13 зовут служебный
|
||||
файл `docs/.pm.json` — так и было; переименование делает запись 13, а переезд в
|
||||
`.av-dev.toml` — запись 1 действующего журнала.
|
||||
|
||||
Проект, отставший от канона 14, идёт сперва по этим записям снизу вверх от своей
|
||||
версии до 14, и только потом переходит в действующий журнал.
|
||||
|
||||
---
|
||||
|
||||
## Версия 14 — 2026-08-11
|
||||
|
||||
У ADR стало два законных источника. Прежде запись цитировала только архивный
|
||||
`design.md`, то есть решение, принятое по ходу изменения. Решение, принятое
|
||||
**разведкой** — намеренный отказ, выбор подхода, «проверили и не делаем», — не
|
||||
имеет `design.md` по построению: change по нему не заводится никогда. Триггер
|
||||
канона такое решение ловит («намеренный отказ от очевидного подхода»), а дома у
|
||||
него не было, и оно оседало в записке разведки или в переписке.
|
||||
|
||||
**Что изменилось.** `adr/` принимает второй источник — записку разведки. Правило
|
||||
«промоут, а не второе сочинение» не тронуто: запись по-прежнему цитирует уже
|
||||
написанное и **называет источник**, изменилось только то, что источников два.
|
||||
Следом сказали то же самое: карта домов, разрез проверки `doc-consistency`, вход
|
||||
и устав самого агента, скелеты `docs/adr/README.md` и `docs/adr/template.md`.
|
||||
|
||||
**Почему это версия, а не правка текста.** Два следствия уезжают в репозиторий
|
||||
проекта. По карте домов судит агент согласованности — прежняя редакция читала ADR
|
||||
со ссылкой на записку разведки как нарушение; а скелеты `adr/` лежат в проекте
|
||||
файлами и говорят там от имени канона.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Ничего с существующими записями: прежние ADR ссылаются на `design.md`, и это
|
||||
по-прежнему верно.
|
||||
2. **Поднять шапку `docs/adr/README.md`**: «промоут поверх архивного `design.md`»
|
||||
→ «промоут поверх уже написанного», с обоими источниками. Точный текст — в
|
||||
[skeletons.md](skeletons.md), раздел `docs/adr/README.md`.
|
||||
3. **Поднять `docs/adr/template.md`**: строка `- **Источник:**` называет два
|
||||
возможных источника.
|
||||
4. `docs/.docs.json`: `"canon": 14`.
|
||||
|
||||
**Чего делать не надо.** Заводить ADR задним числом по старым разведкам. Запись
|
||||
заводится, когда решение принимается, а не когда о нём вспомнили: сочинённое
|
||||
через полгода обоснование — ровно то «второе сочинение», против которого правило
|
||||
и написано.
|
||||
|
||||
---
|
||||
|
||||
## Версия 13 — 2026-08-11
|
||||
|
||||
Служебный файл канона переименован: `docs/.pm.json` → `docs/.docs.json`. Имя
|
||||
досталось от плагина `av-dev-pm`, который распался на четыре и которого больше
|
||||
нет: файл пережил владельца и указывал в пустоту. Правило простое и теперь
|
||||
соблюдается всеми тремя: **имя служебного файла — имя плагина, который его
|
||||
завёл**, `.docs.json` — канон, `.tasks.json` — задачи, `openspec/config.yaml` —
|
||||
конвейер.
|
||||
|
||||
**Что изменилось.** `docs.py` читает только новое имя. Прежнее он не читает
|
||||
намеренно: два дома для одной версии канона расходятся молча, а тут расхождение
|
||||
стоило бы дорого — по этому числу `upgrade` решает, какие записи применять.
|
||||
Файл под старым именем `check` узнаёт и называет отдельной строкой с готовой
|
||||
командой, а не жалуется на пропажу.
|
||||
|
||||
**Что появилось у соседа.** У каталога задач теперь есть **своя версия
|
||||
формата** — ключ `tasks` в `<каталог задач>/.tasks.json`, — и свой журнал версий
|
||||
в скилле `av-dev-tasks:tasks`. До сих пор её не было вовсе: формат задач менялся
|
||||
записями этого журнала (8, 11, 12), хотя каталог принадлежит другому плагину и
|
||||
ставится без канона документов. Канон это число не двигает.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. `git mv docs/.pm.json docs/.docs.json` — одним коммитом с шагом 2. Содержимое
|
||||
не меняется: ключи те же.
|
||||
2. **Поправить упоминания прежнего имени** в своих файлах — `CLAUDE.md`, гейт,
|
||||
`README.md`, `docs/**`. Битой ссылкой это чаще всего не выглядит (файл
|
||||
служебный, на него ссылаются прозой), поэтому `docs.py check` таких упоминаний
|
||||
не ловит: ищи `grep -rn '\.pm\.json'` по репозиторию.
|
||||
3. **Объявить версию формата задач**, если каталог задач в проекте есть:
|
||||
`<каталог задач>/.tasks.json` с ключом `"tasks": <версия>`. Файла нет вовсе —
|
||||
заведи, он теперь обязателен: версия не настройка, от которой можно
|
||||
отказаться. Какое число ставить и что сделать перед этим, говорит журнал
|
||||
владельца — **позови скилл `av-dev-tasks:tasks`**, здесь этих шагов нет
|
||||
намеренно: второй перечень чужих шагов разошёлся бы с первым.
|
||||
4. Гейт не меняется: шаги те же, версию задач сторожит `tasks.py check`, который
|
||||
в нём уже стоит.
|
||||
5. `docs/.docs.json`: `"canon": 13`.
|
||||
|
||||
**Чего делать не надо.** Ключи в файле не трогаются, документы не переезжают,
|
||||
записи задач не меняются: версия 13 — про имена служебных файлов и про то, кто
|
||||
чью версию двигает.
|
||||
|
||||
---
|
||||
|
||||
## Версия 12 — 2026-08-09
|
||||
|
||||
Спринты отменены. Работа идёт задача за задачей, и замороженный набор перестал
|
||||
что-либо удерживать: он отвечал на вопрос «что делать дальше», а между наборами
|
||||
на этот вопрос не отвечал никто.
|
||||
|
||||
**Что изменилось.** Индексов задач два вместо трёх: `SPRINT.md` упразднён.
|
||||
Приоритет стал тем, чем он и является, — **порядком строк в `BACKLOG.md`**:
|
||||
первая строка секции это то, что делают следующим. Назначает порядок человек,
|
||||
машина его не выводит; двигают его `move --after` и `move --first` с причиной.
|
||||
|
||||
Гейт готовности записи стоял на взятии задачи в спринт — единственном месте, где
|
||||
её судили целиком. Момент нужен и без спринта: теперь это команда
|
||||
`tasks.py ready <слаг>`, и зовёт её тот, кто берёт задачу в работу.
|
||||
|
||||
Ритуал между спринтами (`av-dev-tasks:session`) стал скиллом груминга
|
||||
(`av-dev-tasks:groom`): два вопроса — что сейчас самое важное и что перестало
|
||||
быть важным.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. **Вернуть задачи из набора в беклог и снести `SPRINT.md`.** Порядок такой:
|
||||
`git rm tasks/SPRINT.md`, затем `tasks.py check --dir tasks --fix`. Строки
|
||||
набора после удаления файла становятся бездомными, и `--fix` возвращает их в
|
||||
беклог **в конец своей секции** — с пометкой, что позицию назначает человек.
|
||||
Наоборот делать нельзя: `check` без удалённого файла увидит третий индекс и
|
||||
станет ругаться на него, а не чинить.
|
||||
2. **Снять теги `sprint:<слаг>`** с записей — `tasks.py edit <слаг> --rm-tag
|
||||
sprint:<слаг>`. Тег больше никем не читается, а `check` о нём молчит: он
|
||||
законный свободный тег. Пропущенный вреда не сделает, но и пользы не несёт.
|
||||
3. **Расставить порядок** — первый груминг: `av-dev-tasks:groom`. После шага 1
|
||||
очередь состоит из того, что машина поставила в конец, то есть очереди нет
|
||||
вовсе. Пока порядок не назначен, «что делать дальше» по-прежнему без ответа.
|
||||
4. Поправить упоминания спринта в `CLAUDE.md` проекта, если они были: слот
|
||||
«общий станок» переехал в груминг под именем «что считается сломанным»,
|
||||
ориентир «5–8 задач в спринте» стал ориентиром размера порции разбора.
|
||||
5. `docs/.pm.json`: `"canon": 12`.
|
||||
|
||||
**Чего делать не надо.** `REJECTED.md`, `ROADMAP.md` и файлы `items/` не
|
||||
меняются: спринт жил только в собственном индексе и в тегах.
|
||||
|
||||
---
|
||||
|
||||
## Версия 11 — 2026-08-09
|
||||
|
||||
Каталог задач уехал из `docs/` в корень репозитория. Версия 8 отпустила его из
|
||||
канона — перестала требовать, перестала проверять, — но место он занимал всё то
|
||||
же, `docs/tasks/`. Полдела: каталог, принадлежащий одному плагину, лежал внутри
|
||||
дерева, которым владеет другой. Проекту, поставившему учёт работ без канона
|
||||
документов, приходилось заводить `docs/` ради одной вложенной папки.
|
||||
|
||||
**Что изменилось.** Дом задач — `tasks/` в корне репозитория. `tasks.py` ищет его
|
||||
там первым; `docs/tasks/` и `doc/tasks/` остаются в списке поиска для
|
||||
непереехавших проектов, а `init` заводит только в корне. Настройки — там же,
|
||||
`tasks/.tasks.json`.
|
||||
|
||||
**Что осталось терпимым.** `docs.py` по-прежнему не считает `docs/tasks/` файлом
|
||||
вне канона: непереехавший проект не должен получать выдуманную ошибку вдобавок к
|
||||
этой записи, которая и так велит ему переехать.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. `git mv docs/tasks tasks` — одним коммитом вместе с шагом 2, чтобы ссылки не
|
||||
жили битыми между коммитами.
|
||||
2. **Починить относительные ссылки внутри записей.** Файл `tasks/items/x.md`
|
||||
стал на уровень ближе к корню: `../../passport.md` в теле записи теперь
|
||||
`../docs/passport.md`. Тот же сдвиг у ссылок из индексов. Это самая тихая
|
||||
часть переезда: битая относительная ссылка не мешает `tasks.py check`, её
|
||||
ловит только `docs.py check` и только у документов канона.
|
||||
3. Проверить ссылки **на** задачи снаружи: `CLAUDE.md`, `README.md`, гейт,
|
||||
`docs/review.md`. Путь `docs/tasks/...` в них теперь ведёт в никуда.
|
||||
4. Поправить путь в гейте: `tasks.py check --dir tasks`.
|
||||
5. `docs/.pm.json`: `"canon": 11`.
|
||||
|
||||
## Версия 10 — 2026-08-09
|
||||
|
||||
Проверка формы `config.yaml` ушла к тому, кто файл заводит. Версия 9 перенесла в
|
||||
конвейер настройку OpenSpec и честно назвала остаток: форма и сторож версии
|
||||
остались в `docs.py`, то есть у файла было два плагина — один заводит, другой
|
||||
проверяет. Остаток закрыт.
|
||||
|
||||
**Что появилось.** Скрипт `openspec.py` в скилле `av-dev-code:openspec`, две
|
||||
команды: `check --dir <корень>` — форма в проекте, `form` — сверка слепка с живым
|
||||
OpenSpec. Коды выхода те же, что у `docs.py` и `tasks.py`.
|
||||
|
||||
**Что удалено из `docs.py`.** Константы `OPENSPEC_*`, проверка формы, сторож
|
||||
версии и подкоманда `openspec-form` — 252 строки. Скрипт канона про
|
||||
`openspec/config.yaml` не говорит теперь ничего; `openspec/specs/` он по-прежнему
|
||||
знает, потому что это дом темы `requirements` и часть карты тем.
|
||||
|
||||
**Что стало лучше по дороге.** Адреса `docs/passport.md` и `CLAUDE.md` требуются
|
||||
теперь **только к тем документам, которые в проекте есть**. Прежняя проверка
|
||||
требовала их безусловно, то есть на проекте без канона документов требовала
|
||||
битую ссылку. Теперь отсутствие документа — строка «не проверялось» с указанием,
|
||||
что без канона конвейер работает вслепую.
|
||||
|
||||
**Что осталось за каноном.** Один вопрос, и это не форма: не пересказан ли в
|
||||
`context` документ, у которого есть свой дом. Разрез — утверждение, опровергаемое
|
||||
открытием другого файла, против строки «открой такой-то файл»; машине он не
|
||||
виден, судит агент `doc-consistency`, и `config.yaml` у него во входе.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Заменить в гейте и в скриптах `docs.py openspec-form` на `openspec.py form`.
|
||||
Подкоманды больше нет: прежний вызов упадёт ошибкой употребления (код 2), а не
|
||||
промолчит.
|
||||
2. **Добавить в гейт шаг `openspec.py check`, если проект работает по OpenSpec.**
|
||||
Форму раньше проверял `docs.py check` заодно; теперь он о ней молчит, и без
|
||||
отдельного шага незаменённый пример в `config.yaml` перестанет ловиться. Это
|
||||
главная потеря этого повышения, и она тихая.
|
||||
3. Проект по OpenSpec без установленного `av-dev-code` — форму не проверяет
|
||||
никто. Либо поставить плагин, либо назвать это принятым риском вслух.
|
||||
4. `docs/.pm.json`: `"canon": 10`.
|
||||
|
||||
## Версия 9 — 2026-08-09
|
||||
|
||||
OpenSpec уехал в конвейер. Каталог `openspec/` версией 7 был объявлен слотом
|
||||
канона: `init` его заводил, `adopt` тоже, образец `config.yaml` лежал в скелетах,
|
||||
а отсутствие каталога `docs.py` считал отказом. Разрез был проведён не там. По
|
||||
OpenSpec работает конвейер — без каталога не запускаются ни `opsx:propose`, ни
|
||||
ревью дизайна, ни сверка требований, — а канон документов о нём только
|
||||
высказывался. Проект, которому конвейер не нужен, получал отказ за отсутствие
|
||||
того, чем не пользуется.
|
||||
|
||||
**Что появилось.** Скилл `av-dev-code:openspec`: заводит каталог, заменяет
|
||||
закомментированный пример в `config.yaml` настройкой, объясняет разрез между
|
||||
ссылкой и пересказом. Образец файла переехал туда же — в
|
||||
`references/config-skeleton.md` того скилла.
|
||||
|
||||
**Что изменилось.** `init` и `canon adopt` OpenSpec больше не заводят, а **зовут
|
||||
скилл конвейера**; вызов не разрешился — плагина конвейера нет, и это строка
|
||||
доклада, а не поломка. Отсутствие `openspec/` для `docs.py check` стало
|
||||
неприменимостью вместо отказа: остальные четыре проверки формы идут только при
|
||||
живом каталоге.
|
||||
|
||||
**Что осталось на месте и почему.** Проверка формы `config.yaml` и сторож версии
|
||||
(`docs.py openspec-form`) пока живут в скрипте канона — переносить их значит
|
||||
заводить в конвейере свой скрипт, а этого у него нет ни одного. Разрез названного
|
||||
это не отменяет, но и не завершает: **у файла сейчас два плагина — один заводит,
|
||||
другой проверяет**, и это временное состояние, а не задуманное.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Ничего не переносить: файлы проекта эта версия не двигает. Меняется только то,
|
||||
кто их заводит.
|
||||
2. Проверить, что плагин `av-dev-code` установлен, если проект работает по
|
||||
OpenSpec. Без него `docs.py check` про каталог промолчит — и молчание это
|
||||
законное, так что отсутствие настройки перестанет ловиться само.
|
||||
3. Проект **не** работает по OpenSpec: убедиться, что `openspec/` нет, и
|
||||
перестать держать его пустым ради проверки. Она больше не требует каталога.
|
||||
4. `docs/.pm.json`: `"canon": 9`.
|
||||
|
||||
## Версия 8 — 2026-08-09
|
||||
|
||||
Канон отпустил каталог задач. Плагин `av-dev-pm` расколот на `av-dev-docs`
|
||||
(документы) и `av-dev-tasks` (учёт работ), и каждый теперь ставится сам по себе.
|
||||
Пока владелец был один, `docs/tasks/` числился слотом канона: `docs.py` требовал
|
||||
каталог, звал внутрь чужой скрипт и выдавал его дрейф за свой, а настройки задач
|
||||
жили ключом `tasks` в `docs/.pm.json`. Для проекта, поставившего только документы,
|
||||
всё это — отказ на ровном месте: задач он не ведёт, и требовать их не за что.
|
||||
|
||||
**Что изменилось.** Каталог задач канону не принадлежит; канон резервирует ему
|
||||
место в `docs/` и внутрь не смотрит. `docs.py` больше не проверяет согласованность
|
||||
задач вовсе — это делает `tasks.py` сам, командой своего плагина. Дом настроек
|
||||
каталога задач — `<каталог задач>/.tasks.json`; ключ `tasks` в `docs/.pm.json`
|
||||
читается, только пока своего файла нет, и об этом говорится замечанием.
|
||||
|
||||
**Что удалено.** Проверка `check_tasks` из `docs.py` и ключ `"tasks"` из скелета
|
||||
`docs/.pm.json`.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Перенести настройки задач: содержимое ключа `"tasks"` из `docs/.pm.json` — в
|
||||
`docs/tasks/.tasks.json` тем же объектом. Ключа в проекте нет (имена файлов
|
||||
и заголовков умолчательные) — переносить нечего, шаг пропускается.
|
||||
2. Удалить ключ `"tasks"` из `docs/.pm.json` после переноса. Оставленный он не
|
||||
читается, и `tasks.py` скажет об этом замечанием на каждом прогоне.
|
||||
3. Проверить, что согласованность задач по-прежнему кто-то гоняет: раньше её
|
||||
тянул за собой `docs.py check`, теперь — только `tasks.py check`. **Если в
|
||||
гейте проекта стоял один `docs.py`, добавить туда второй шаг** — иначе дрейф
|
||||
индексов перестанет ловиться молча, и это самая вероятная потеря на этом
|
||||
повышении.
|
||||
4. Установить оба плагина, если нужны оба: `av-dev-docs` и `av-dev-tasks`
|
||||
вместо прежнего `av-dev-pm`. Прежний из `enabledPlugins` убрать.
|
||||
5. `docs/.pm.json`: `"canon": 8`.
|
||||
|
||||
## Версия 7 — 2026-08-07
|
||||
|
||||
`openspec/` был предпосылкой, о которой канон говорил, но за которой не следил.
|
||||
Каталог назван в раскладке, `openspec/specs/` объявлен домом темы `requirements`,
|
||||
`config.yaml` описан абзацем — а заводил всё это человек руками, и проверялось
|
||||
из перечисленного ничего. Заведение нового проекта проходило мимо: `init`
|
||||
собирал документы канона и оставлял проект без каталога, без которого не работают
|
||||
ни `opsx:propose`, ни ревью дизайна, ни сверка требований.
|
||||
|
||||
Хуже отсутствия оказался файл из коробки. `openspec init` кладёт `config.yaml`,
|
||||
где `context` и `rules` — закомментированный пример на английском. Такой файл
|
||||
читается как настроенный: он есть, он валиден, имя правильное. Работает он как
|
||||
пустой, и узнаётся это по предложению, написанному на другом языке, с
|
||||
capability по имени пакета и без единого `SHALL`.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **`init` заводит OpenSpec сам** — `openspec init --tools claude`, до первого
|
||||
документа канона. Команда названа в каноне поимённо, потому что её печатает
|
||||
отказ `docs.py`.
|
||||
2. **У `openspec/config.yaml` появилась каноническая форма** и скелет в
|
||||
`skeletons.md`. Содержание — только то, что нужно **в момент порождения
|
||||
артефакта**: язык, правила именования capability, придирки валидатора и
|
||||
**адреса** документов канона. Пересказ паспорта, инвариантов, конвенций и
|
||||
правил ревью в него не переносится.
|
||||
3. **`docs.py check` проверяет пять вещей:** каталог `openspec/` есть; файл
|
||||
называется `config.yaml` (`config.yml` OpenSpec читать не станет и об этом не
|
||||
сообщит); `context` и `rules.specs` не остались примером, а правила для
|
||||
`specs` называют `SHALL`; `context` называет `passport` и `CLAUDE.md`; ключи
|
||||
под `rules:` — имена артефактов схемы, а не опечатки.
|
||||
4. **За свежестью формы следит машина, а не память.** Схема и перечень
|
||||
артефактов — слепок чужого инструмента; `check` сравнивает `major.minor`
|
||||
установленного OpenSpec с версией, на которой форма сверялась, и при
|
||||
расхождении даёт замечание. Перепроверяет `docs.py openspec-form`, и чинится
|
||||
расхождение **в плагине, а не в проекте**.
|
||||
5. **Шестое проверяет агент.** Отличить ссылку на документ от пересказа документа
|
||||
машина не умеет — это работа `doc-consistency`, и в таблице «Что проверяет
|
||||
машина, а что человек» она стоит строкой.
|
||||
|
||||
**Что переехало:** ничего в раскладке `docs/`. Ни один файл не переименовывается
|
||||
и не перемещается.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Нет `openspec/` — завести: `openspec init --tools claude`. Команда кладёт ещё
|
||||
и `.claude/skills/openspec-*` с `.claude/commands/opsx/*`; это её нормальная
|
||||
работа, удалять их не надо.
|
||||
2. Открыть `openspec/config.yaml` и привести к скелету из
|
||||
[skeletons.md](skeletons.md): блок `context` с языком, правилами именования
|
||||
capability, требованием `SHALL` и **адресами** `docs/passport.md` и
|
||||
`CLAUDE.md`; блок `rules` с четырьмя правилами для `specs`.
|
||||
3. **Вычистить из `context` пересказ.** Инварианты, перечень конвенций, состав
|
||||
шагов гейта, правило выбора метки и состав проходов ревью — заменить ссылкой
|
||||
на дом. Признак пересказа простой: строку можно опровергнуть, открыв другой
|
||||
файл проекта.
|
||||
4. Проверить имя файла: `config.yml` переименовать в `config.yaml`. Если жили оба
|
||||
— содержимое `.yml` до сих пор не читалось никем, и переносить из него нужно
|
||||
именно то, чего нет в `.yaml`.
|
||||
5. `docs/.pm.json`: `"canon": 7`.
|
||||
|
||||
---
|
||||
|
||||
## Версия 6 — 2026-08-07
|
||||
|
||||
Версия 5 объявила: **каждый документ `docs/` — тема ревью**. Правило оказалось
|
||||
верным ровно наполовину и потому вредным целиком. Паспорт и схему хранилища
|
||||
ревью читает, но темами они не являются — они задают границу, по которой судит
|
||||
чужая тема. Журнал решений и журнал наблюдений ревью изменения не нужны вовсе:
|
||||
ADR объясняет прошлое решение, а не предъявляет требование к изменению.
|
||||
|
||||
Разметчик, применявший плоское правило буквально, обязан был либо завести
|
||||
фантомные темы `passport`, `adr`, `database`, `research` и продублировать ими
|
||||
работу тем `architecture` и `operations`, либо потерять четыре документа молча —
|
||||
а молчащая потеря и есть то, против чего канон написан.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **Три категории документов вместо одной.** Разрез проверяемый: можно ли по
|
||||
документу сказать «в этом изменении сделано не так»? **Тема** — да, прямо
|
||||
(`conventions`, `security`, `architecture`, свои документы проекта).
|
||||
**Источник темы** — нет, но он задаёт границу для чужой темы (`passport.*` →
|
||||
`architecture`, `database.*` → `operations`, `CLAUDE.md` → `autotests`,
|
||||
`openspec/specs/` → `requirements`). **Процессный документ** — нет, он про то,
|
||||
как мы работаем (`tasks/`, `review.*`, `adr.*`, `research.*`, `.pm.json`).
|
||||
2. **Категории `источник` и `процессный` закрыты, категория `тема` открыта.**
|
||||
Прежде открытым был весь список, и «не темы ровно две» противоречило
|
||||
собственной раскладке канона. Теперь пополняется только одно множество, и
|
||||
документ, которого нет в раскладке, — однозначно своя тема проекта.
|
||||
3. **`adr/` и `research/` уходят из входа ревью изменения.** Прогон их больше не
|
||||
открывает. Проверяться они не перестали: ADR без ссылки на архивный
|
||||
`design.md`, замена без парного статуса, число без провенанса — это по-прежнему
|
||||
работа `doc-consistency` и `doc-code-drift`, на сессии между спринтами.
|
||||
4. **`docs.py` печатает категорию в отказе.** «Нет источника passport» читается
|
||||
иначе, чем «нет темы security». Обязательность при этом не изменилась:
|
||||
заводятся все документы одинаково и с первого дня.
|
||||
5. **У задачи появилась метка — `small`, `medium` или `large`.** Это итог
|
||||
классификации и **единственный вход, по которому конвейер выбирает
|
||||
исполнителей** на обеих стадиях ревью. Прежние имена `quick`, `standard` и
|
||||
`wide` описывали глубину прогона, то есть свойство ревью; метка описывает
|
||||
**задачу** — а выбирают по ней одно и то же. Слово «ступень» уходит:
|
||||
у одной вещи одно имя.
|
||||
6. **Метка выводится из двух осей и не равна ни одной из них.** Размер (малое,
|
||||
среднее, крупное) и сложность (знакомое, незнакомое); метка — максимум по
|
||||
ним. Малое **незнакомое** изменение получает `large`, трогая один узел, —
|
||||
поэтому размер и метка пишутся отдельными строками, и выводить одно из
|
||||
другого нельзя.
|
||||
|
||||
**Цена, записанная явно:** расхождение изменения с записанным решением прогоном
|
||||
больше не ловится. Раньше архитектурный проход мог сказать «здесь отменено
|
||||
решение ADR-2026-03-11, парного статуса нет»; теперь это скажет только сверка
|
||||
документации. Сделка сознательная: чтение всего каталога решений оплачивалось на
|
||||
каждой задаче, а срабатывало на единицах.
|
||||
|
||||
**Что переехало:** ничего в раскладке. Ни один файл не переименовывается и не
|
||||
перемещается.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. `docs/review.*`, подраздел «Вопросы по темам»: убрать вопросы, адресованные
|
||||
`passport`, `database`, `adr`, `research` и `review` — **ни одно из этих имён
|
||||
больше не тема**. Под каноном 5 темой был каждый документ `docs/`, поэтому
|
||||
такие вопросы там законны и почти наверняка есть. Переадресовать:
|
||||
про границу домена и про решение → `architecture`; про хранилище, настройку и
|
||||
измеренное число → `operations`. Вопрос, который никуда не переадресовывается,
|
||||
удалить, а не оставить висеть: адресованный несуществующей теме, он не
|
||||
задаётся никем и молча.
|
||||
2. Там же, «Недоступно проверке»: те же пять имён убрать из разнесения по темам,
|
||||
переразнеся содержимое по оставшимся.
|
||||
3. Там же: подраздел **«Триггеры профиля» → «Триггеры метки»**, и разнести его
|
||||
на **три** списка вместо двух — «крупное здесь» (про объём), «незнакомое
|
||||
здесь» (про форму решения) и «мелкое здесь» (опускает до `small`). Раньше
|
||||
первые две оси были склеены в один список, и потому объём в правило по факту
|
||||
не входил.
|
||||
4. **Переименовать метки прогона везде, где проект их называет** — в «Триггерах
|
||||
метки», в «Недоступно проверке», в журнале дефектов: `quick` → **`small`**,
|
||||
`standard` → **`medium`**, `wide` → **`large`**. Метка это итог классификации
|
||||
задачи, и три её значения — часть общего словаря канона и конвейера. Слово
|
||||
«ступень» из документов уходит: у одной вещи одно имя.
|
||||
5. Проверить, что свои темы проекта не совпадают именем с закрытыми категориями:
|
||||
`docs/passport/`, `docs/adr/`, `docs/research/`, `docs/database/`,
|
||||
`docs/review/` — это слоты канона, а не свои темы, и своим смыслом их
|
||||
наполнять нельзя.
|
||||
6. Ничего не заводить и не удалять: раскладка канона 6 совпадает с раскладкой
|
||||
канона 5 файл в файл.
|
||||
7. `docs/.pm.json`: `"canon": 6`.
|
||||
|
||||
---
|
||||
|
||||
## Версия 5 — 2026-08-06
|
||||
|
||||
Канон перестал быть списком файлов и стал **списком тем ревью**. Раскладка та же,
|
||||
но читается иначе: документ в `docs/` — это направление проверки, а не просто
|
||||
текст. Отсюда три правки, и все три развязывают то, что раньше было жёстко
|
||||
сцеплено.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **Тема живёт файлом или каталогом, на выбор проекта.** `docs/security.md` и
|
||||
`docs/security/` — одно и то же; тема разрослась, стала каталогом с
|
||||
`README.md` — канон не сменился и версия не двинулась. Прежде форма была
|
||||
задана поимённо: `conventions`, `research` и `adr` обязаны были быть
|
||||
каталогами, остальные — файлами, и обосновать это было нечем. Обе формы сразу
|
||||
— ошибка: два дома для одного факта расходятся молча.
|
||||
2. **Список тем открытый.** Всё, что проект кладёт в `docs/`, становится темой
|
||||
ревью и попадает в план каждого прогона; именной оптики у такой темы нет, её
|
||||
разбирает общий проход конвейера, заведённый ровно за этим.
|
||||
Прежде `docs.py` называл незнакомый файл «вне канона» — теперь называет своей
|
||||
темой проекта и перечисляет их в отчёте. Не темы ровно две: `docs/tasks/` и
|
||||
`docs/review.*`.
|
||||
3. **`AGENTS.md` рядом с `CLAUDE.md` — законно.** Он почти стандарт; обязателен
|
||||
по-прежнему только `CLAUDE.md`, но если лежат оба, читаются оба, и проверки
|
||||
канона смотрят на второй так же, как на первый.
|
||||
|
||||
**Что переехало:**
|
||||
|
||||
- в `docs/review.*`: **«Вопросы к проходам» → «Вопросы по темам»**, форма
|
||||
`<тема>: <вопрос> (<провенанс>)`. Причина не косметическая: вопрос,
|
||||
адресованный проходу, перестал задаваться молча в тот день, когда тот уехал в
|
||||
верхнюю ступень ревью. Тема переезд прохода переживает, имя прохода — нет;
|
||||
- там же **«Недоступно проверке» — по темам**, оба подраздела.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Ничего не переименовывать, если всё уже разложено по канону 4: обе формы
|
||||
дома законны, и текущая — одна из них.
|
||||
2. `docs/review.*`, подраздел «Вопросы к проходам»: переименовать в «Вопросы по
|
||||
темам» и переадресовать каждый вопрос теме вместо имени прохода. Темы ядра —
|
||||
`requirements`, `autotests`, `conventions`, `architecture`, `security`,
|
||||
`operations`.
|
||||
3. Там же «Недоступно проверке»: разнести обе половины по темам.
|
||||
4. Проверить, не лежит ли в `docs/` документ, который раньше считался лишним и
|
||||
потому не заводился. Теперь он законен и станет темой ревью — это и есть
|
||||
способ добавить проверку, которой в конвейере нет.
|
||||
5. `docs/.pm.json`: `"canon": 5`.
|
||||
6. Позвать судей `doc-consistency` и `doc-code-drift` — шагом 6 `upgrade`.
|
||||
|
||||
## Версия 4 — 2026-08-05
|
||||
|
||||
Две правки, обе про то, как читается каталог задач. Первая — секция роадмапа
|
||||
переименована, и вместе с именем расширен её смысл; достигнутое переехало вниз.
|
||||
Вторая — **у каждой записи появился тип, и тип определяет, что с записью можно
|
||||
делать**. Раскладка не меняется, файлов канона не прибавляется.
|
||||
|
||||
**Что переехало:**
|
||||
|
||||
- секция роадмапа `Разработка` → **`Сопровождение`** (англ. `Tooling` →
|
||||
**`Operations`**). Прежнее имя называло слишком много: роадмап **весь** про
|
||||
разработку, и секция с таким именем не отличалась от остальных ничем;
|
||||
- **тип записи** — из префикса заголовка (`[goal]`/`[idea]`) и тега
|
||||
`kind:<род>` в **поле меты `Тип`** первой строкой. Эмодзи в заголовке от него
|
||||
производна;
|
||||
- **поле места** у задачи: `Секция` → **`Категория`**. У цели остаётся `Секция`:
|
||||
у задачи поле называет полку домена, в которую она вернётся из спринта, у цели
|
||||
— часть роадмапа, то есть состояние очереди. Одно имя на два смысла их и
|
||||
смешивало.
|
||||
|
||||
**Что добавилось:**
|
||||
|
||||
1. **Смысл секции расширен.** Было «инструмент и процесс», стало «чем держат
|
||||
проект: инструмент, процесс, эксплуатация». Метрики, логи, инфраструктура,
|
||||
выкладка и дежурство — сюда же. Расширение не косметическое: английское
|
||||
`Operations` при узком смысле обещало бы эксплуатацию, а внутри лежал бы
|
||||
линтер.
|
||||
2. **Общий словарь трёх мест** — [canon.md](canon.md), раздел «Сопровождение и
|
||||
эксплуатация». Сопровождение — всё, чем держат проект; эксплуатация — его
|
||||
часть, работа системы на проде. `ROADMAP.md`, секция `Сопровождение` — план
|
||||
работ; `architecture.md`, раздел «Эксплуатация» — как устроено сейчас;
|
||||
эксплуатационный проход ревью — оптика проверки. Слить их в одно слово
|
||||
нельзя: они отвечают на разные вопросы. Слово **«поддержка» не употребляется
|
||||
вовсе** — в нём слышится помощь пользователю.
|
||||
3. **Граница с возможностями проходит по тому, кто наблюдает.** «Приложение
|
||||
сообщает о своём состоянии» — возможность приложения, её место среди прочих
|
||||
целей. «Дежурный видит состояние на одном экране» — сопровождение. Одни и те
|
||||
же метрики попадают в разные секции роадмапа, и это верно.
|
||||
4. **Порядок секций стал каноническим**, и `Готово` переехало **вниз**:
|
||||
`Запланировано` | `Направления` | `Сопровождение` | `Готово`. Достигнутое
|
||||
копится — через год этой секции больше, чем всех остальных вместе, — и стоя
|
||||
первой она отодвигает за экран то, ради чего роадмап открывают чаще всего.
|
||||
Порядок проверяет `tasks.py check`, переставляет `check --fix`.
|
||||
5. **Заголовок секции отбивается пустой строкой с обеих сторон.** Прежде
|
||||
проверялась только строка после заголовка; перестановка секций двигает целые
|
||||
блоки, и два заголовка оказываются вплотную. Правит `check --fix`.
|
||||
6. **Тип — единственная ось записи, закрытый словарь из пяти значений:**
|
||||
`goal` | `feature` | `fix` | `chore` | `research`. Осей было две — тип записи
|
||||
(`goal`/`idea`/`task`) и род работы (`kind:` тегом), — но из двенадцати
|
||||
клеток произведения законны были шесть, а алгоритм работы крепится к роду, а
|
||||
не к типу. Оси схлопнуты.
|
||||
7. **Тип задаёт схему тела:** какие разделы обязательны, какие допустимы, нужна
|
||||
ли цель, берётся ли запись в спринт. Проверяет `sprint take`, замечания даёт
|
||||
`check`. Два раздела новые: **`Воспроизведение`** у `fix` (не
|
||||
воспроизводится — это `research`, а не `fix`; правило было записано и не
|
||||
проверялось) и **`Вопрос` + `Куда ляжет ответ`** у `research` вместо
|
||||
критериев приёмки (приёмка разведки — записанный ответ, и критерии в форме
|
||||
«оракул: тест» ей натянуты).
|
||||
8. **Тип `idea` упразднён.** Он значил не род работы, а состояние
|
||||
незаполненности, а состояние типом быть не может. Теперь оно называется
|
||||
честно: `research` без раздела «Вопрос» — **сырьё**. В спринт не берётся, как
|
||||
и прежняя идея, лежит **в конце своей категории** (проверяет `check`,
|
||||
переставляет `--fix`) и отбирается `list --raw`. Порядка «по важности» в
|
||||
беклоге по-прежнему нет: этот порядок производен от типа, а не назначен
|
||||
человеком.
|
||||
9. **Алгоритм работы над каждым типом** — отдельным файлом,
|
||||
`skills/tasks/references/task-<тип>.md`: схема, что проверяет машина, что
|
||||
человек, и порядок шагов.
|
||||
10. **Имена файлов проверяются.** Правило «текст русский, имена английские»
|
||||
стояло в каноне и не было подкреплено ничем: `docs.py` имён не смотрел вовсе.
|
||||
Теперь смотрит — кириллица и не-kebab-case **жёстко**, форма имени
|
||||
`ADR-ГГГГ-ММ-ДД-slug.md` жёстко, транслит **эвристикой**, то есть
|
||||
замечанием. Заодно из раскладки канона убраны плейсхолдеры `<тема>.md`,
|
||||
приглашавшие называть файлы по-русски.
|
||||
11. **Два агента вместо обещания.** В каноне была таблица «Что проверяет машина,
|
||||
а что человек», и её правая колонка три версии описывала судью, которого не
|
||||
существовало. Судьи заведены и разведены по глубине: **`doc-consistency`**
|
||||
(документ ↔ документ ↔ openspec: факт в двух домах, прямое противоречие,
|
||||
поведение в `architecture.md` вместо спек, ADR без ссылки и парного статуса,
|
||||
число без провенанса, заглушка вместо честной строки); **`doc-code-drift`**
|
||||
(документ ↔ код по закрытому перечню фактов). Оба зовутся раз в спринт на
|
||||
сессии, а также после adopt и после upgrade, на весь канон разом.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Переименовать заголовок секции в `docs/tasks/ROADMAP.md`: `## Разработка` →
|
||||
`## Сопровождение` (или `## Tooling` → `## Operations`, если индекс
|
||||
английский). **`check --fix` этого не сделает**: регистр канонической секции
|
||||
он правит сам, а чужую секцию только называет ошибкой — смысл за человеком.
|
||||
2. Поправить поле `- **Секция:**` в файлах целей, которые в ней лежат. Порядок
|
||||
именно такой: сперва заголовок, потом `python3 tasks.py check --dir
|
||||
docs/tasks` покажет расхождение поимённо.
|
||||
3. Перечитать состав секции: цели про выкладку, метрики, логи и инфраструктуру,
|
||||
если они лежали в `Направлениях` за неимением места, переезжают сюда.
|
||||
4. Прогнать `python3 tasks.py check --dir docs/tasks --fix`. За один проход он
|
||||
переставит секции роадмапа в канонический порядок (`Готово` уедет вниз вместе
|
||||
со всем содержимым), поправит отбивку заголовков и **переведёт записи на
|
||||
типы**: перенесёт значение из тега `kind:` и префикса `[goal]`/`[idea]` в поле
|
||||
`Тип`, снимет тег, поставит эмодзи в заголовок, переименует `Секция` →
|
||||
`Категория` у задач и снесёт сырьё в конец категорий.
|
||||
5. Разобрать то, что `--fix` вернул пометкой `НЕОДНОЗНАЧНО`. Главный случай —
|
||||
**записи без типа**: заведённые до появления рода работы, они не несут ни
|
||||
тега, ни префикса, и машина их не угадывает (`feature` от `chore` не
|
||||
отличает). Проставить руками: `edit <слаг> --type …`.
|
||||
6. Дописать новые обязательные разделы у задач, которые собираются в спринт:
|
||||
`Воспроизведение` у каждого `fix`, `Вопрос` и `Куда ляжет ответ` у каждого
|
||||
`research`. Не «заодно по всему беклогу», а порциями переоценки: `check`
|
||||
ошибкой это не считает, отказывает только `sprint take`. Сколько задач готово
|
||||
к взятию, печатает блок здоровья `check`.
|
||||
7. Прогнать `python3 docs.py check`: он назовёт имена файлов не по правилу.
|
||||
Кириллицу и не-kebab-case править обязательно, транслит — по решению
|
||||
человека. **Переименование ADR это перенос ссылок**: слаг стоит в
|
||||
`adr/README.md`, в `architecture.md` и в чужих документах, и делается одним
|
||||
проходом, иначе останутся битые ссылки (их `docs.py` потом и покажет).
|
||||
8. `docs/review.md`, подраздел «Триггеры профиля» — переписать целиком, он
|
||||
отстал дважды. Снести перечень мест для `deep`: профиль упразднён вместе с
|
||||
проходом независимой реализации, и перечень стал указателем в пустоту.
|
||||
Оставшийся перечень перевести на новое правило: `wide` теперь означает не
|
||||
«новое понятие», а **крупное или незнакомое** изменение и рассчитан на 5–10%
|
||||
задач; отдельным списком назвать, что здесь считается **мелким** (это `quick`).
|
||||
Форма подраздела — в [skeletons.md](skeletons.md). Там же проверить журнал
|
||||
дефектов и «Недоступно проверке» на упоминания независимой реализации: класс
|
||||
«форма решения, где спека выбора не сделала» переезжает в подраздел «перестали
|
||||
проверять сознательно», а рядом с ним встаёт вторая честная строка — на
|
||||
`quick` и `standard` не проверяется ничего, что требует запуска.
|
||||
9. `docs/.pm.json`: `"canon": 4`.
|
||||
10. Позвать **обоих судей** — `doc-consistency` и `doc-code-drift`, шагом 6
|
||||
`upgrade`. Пунктов выше десять, половина из них ручная, и именно здесь видно,
|
||||
какие сделаны только наполовину: переименования секций и полей разводят
|
||||
документы, а `check` сверяет число версии, а не существо. Первый прогон на
|
||||
живом проекте вдобавок самый урожайный — правило единственного дома до сих пор
|
||||
никто не проверял. Разбирать порциями, а не одним заходом.
|
||||
|
||||
## Версия 3 — 2026-08-04
|
||||
|
||||
Роадмап стал **состоянием проекта**, а не очередью работ: цель — возможность
|
||||
приложения, задача — шаг к ней, достигнутое из роадмапа не исчезает. Плюс род
|
||||
работы, раздел «Затрагивает» и новое умолчание профиля ревью. Раскладка меняется
|
||||
в одном файле, но переименование и смена секций тянут за собой ссылки, поэтому
|
||||
шаги делаются одним заходом.
|
||||
|
||||
**Что добавилось:**
|
||||
|
||||
1. **Род работы** — тег `kind:<род>` в мете задачи, словарь закрыт:
|
||||
`feature` | `fix` | `chore` | `research`. Обязателен у задачи, у цели
|
||||
запрещён. `sprint take` без него отказывает, `check` о пропаже напоминает
|
||||
замечанием. Определение — [canon.md](canon.md), раздел `tasks/`; смысл и
|
||||
причина, почему тегом, — в SKILL.md скилла `tasks`, раздел «Род работы».
|
||||
2. **Раздел «Затрагивает»** в теле задачи — перечень границ, которых изменение
|
||||
касается (эндпоинт, таблица и миграция, формат на диске, публичный тип). Как
|
||||
и критерии приёмки, требуется к взятию в спринт, а не к заведению.
|
||||
3. **Секции роадмапа** — четыре вместо двух и **канонические**, в отличие от
|
||||
секций беклога: `Готово` (достигнутые цели строкой с датой, без ссылки на
|
||||
файл), `Запланировано` (очередь значима), `Направления` (очереди нет),
|
||||
`Разработка` (инструмент и процесс, не возможности приложения). Английский
|
||||
вариант — `Done` | `Planned` | `Directions` | `Tooling`, один язык на весь
|
||||
индекс. Переименованию проектом не подлежат: у каждой свой смысл, и в первую
|
||||
пишет сам `close`; `tasks.py check` проверяет состав.
|
||||
4. **Форма заголовка записи** — по типу: задача отвечает на «что нужно сделать»
|
||||
и пишется глаголом в неопределённой форме («Не отбрасывать молча лишние
|
||||
символы»), цель — на «что приложение будет уметь», идея просто называет, о
|
||||
чём она. `check` считает заголовки не в форме действия и печатает число в
|
||||
блоке здоровья. Годность формулировки — не машине: её смотрит новый агент
|
||||
`task-form` (форма записи, только чтение), а язык текста — `doc-wording`.
|
||||
5. **Заголовки секций — с прописной, после заголовка пустая строка**, во всех
|
||||
индексах. Написание канонических секций и отбивку правит `check --fix`; он
|
||||
же сводит написание секции в мете файла с заголовком индекса.
|
||||
6. **Язык проектных текстов** — [language.md](language.md), общий дом для
|
||||
документов канона, задач, решений ADR и записок разведки: информационный
|
||||
стиль (глагол вместо отглагольного существительного, активный залог, факт
|
||||
вместо оценки, стоп-слова, параллельность), таблицы англицизмов и жаргона и
|
||||
то, что из стиля отброшено намеренно. Проектных файлов не добавляет и
|
||||
раскладку не меняет — это правила письма, а не новый слот.
|
||||
7. **Умолчание профиля ревью сменилось** — это не раскладка, но проектный текст
|
||||
под него уже написан. `standard` стал рабочим умолчанием: миграция схемы,
|
||||
публичный контракт и инвариант ступень больше **не** поднимают, `wide`
|
||||
означает новое понятие или структурную единицу. Подраздел «Триггеры профиля»
|
||||
в `docs/review.md` остаётся на месте, но его содержимое надо перечитать.
|
||||
|
||||
**Что переехало:** `docs/tasks/PLAN.md` → `docs/tasks/ROADMAP.md`; достигнутая
|
||||
цель — из небытия в секцию `Готово`: `close <цель> --implemented` удаляет файл, но
|
||||
**оставляет строку с датой**. Прежде роадмап отвечал только «что осталось», и
|
||||
половину его вопроса вели прозой руками. Вместе с
|
||||
файлом переименован ключ конфига `tasks.plan` → `tasks.roadmap` и токены
|
||||
команд: `--index plan` → `--index roadmap`, `init --plan-sections` →
|
||||
`--roadmap-sections`, `init --plan` → `--roadmap`. Старый ключ в
|
||||
`docs/.pm.json` не игнорируется молча — `tasks.py` останавливается и называет
|
||||
переименование.
|
||||
|
||||
**Что удалено:** тип `[epic]`. Он был зонтиком между целью и задачами; зонтиком
|
||||
стала цель, а слишком крупный шаг дробится на шаги помельче под ней. Ноль
|
||||
употреблений на 97 записей двух живых проектов.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. `git mv docs/tasks/PLAN.md docs/tasks/ROADMAP.md`.
|
||||
2. Починить ссылки на прежнее имя: `grep -rn 'PLAN\.md' docs/ CLAUDE.md` —
|
||||
заголовок самого файла («# План» → «# Роадмап»), строка в `docs/tasks/BACKLOG.md`,
|
||||
упоминания в `docs/passport.md` и в телах задач.
|
||||
3. `docs/.pm.json`: ключ `tasks.plan`, если он там был, — в `tasks.roadmap`.
|
||||
4. Проставить род работы живым задачам: `python3 tasks.py check --dir docs/tasks`
|
||||
перечислит те, у кого его нет. Задним числом весь беклог не переоформляется —
|
||||
род нужен к взятию, так что порядок такой: сперва то, что берётся в ближайший
|
||||
спринт, остальное по ходу переоценки.
|
||||
5. Дописать раздел «Затрагивает» — тем же порядком и по той же причине: сперва
|
||||
набор спринта, остальное по мере того, как задача попадает в работу.
|
||||
6. Перечитать «Триггеры профиля» в `docs/review.md`: строки вида «миграция →
|
||||
`deep`» теперь дублируют умолчание с обратным знаком. Оставить там только то,
|
||||
что для этого проекта считается **новым понятием** и **правилом
|
||||
идентичности**, — и убрать остальное, иначе проект возвращает себе прежнюю
|
||||
частоту полного набора уточнением.
|
||||
7. Переименовать секции роадмапа: `порядок` → `Запланировано`, `темы` →
|
||||
`Направления`; завести `Готово` **первой** и `Разработка` последней
|
||||
(порядок секций поменялся в версии 4 — если едешь сразу на неё, заводи
|
||||
`Готово` последней и не переставляй дважды).
|
||||
Прозаические разделы вроде «Что уже пройдено», которые велись руками,
|
||||
разложить: звенья — строками в `Готово` (дата, слаг, что стало возможно),
|
||||
обоснование очереди оставить прозой в `Запланировано`. Любой `##` в индексе
|
||||
проверка считает секцией, и теперь `check` называет чужую секцию ошибкой.
|
||||
8. Переформулировать цели ответом на **«что приложение будет уметь»**: не
|
||||
«Работа со слиянием», а «Исход слияния не зависит от порядка доставки».
|
||||
Свойство поведения — законная цель. Цель, которая не про приложение
|
||||
(процесс, инструмент), переезжает в `Разработка`.
|
||||
9. `[epic]`, если он в проекте заводился: это либо цель, либо набор задач под
|
||||
общей целью. `check` назовёт его неизвестным типом.
|
||||
10. Прогнать `python3 tasks.py check --dir docs/tasks --fix`: он поднимет
|
||||
написание канонических секций, поставит отбивку после заголовков и сведёт
|
||||
секцию в мете файлов с заголовками индексов. Секции беклога проект
|
||||
переименовывает сам — их имена он выбирал, и трогать их скрипт не вправе.
|
||||
11. Переписать заголовки задач в форму действия — по мере того, как задача
|
||||
попадает в работу, а не «заодно»: `check` печатает их число, а `task-form`
|
||||
предложит формулировки на замену пачкой.
|
||||
12. Прочитать [language.md](language.md) — и **ничего не переписывать задним
|
||||
числом**. Правила языка применяются к тому, что пишется и правится сейчас;
|
||||
сплошная вычитка старых документов стоит дороже, чем даёт.
|
||||
13. `docs/.pm.json`: `"canon": 3`.
|
||||
|
||||
## Версия 2 — 2026-08-03
|
||||
|
||||
Шапка записи ADR — мета-блоком общей формы, и у статуса появился объявленный
|
||||
дом. Раскладка не менялась: правка касается одного шаблона.
|
||||
|
||||
**Что добавилось:** поле `- **Статус:**` в шапке `docs/adr/template.md` —
|
||||
`заменено на ADR-…` либо `устарело`, у активной записи поля нет. Правило
|
||||
«старая запись получает статус» было и раньше ([canon.md](canon.md), `adr/`),
|
||||
но места под него шаблон не отводил: каждая запись изобретала своё, а колонка
|
||||
«Статус» таблицы `adr/README.md` брала его оттуда, где он у каждого свой.
|
||||
|
||||
**Что переехало:** поля `Дата` и `Источник` в шаблоне стали жирными
|
||||
(`- **Дата:**`, `- **Источник:**`) — та же форма, что у меты задачи и у записи
|
||||
журнала дефектов: поле на строку, имя жирным.
|
||||
|
||||
**Что удалено:** ничего.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Привести `docs/adr/template.md` к скелету версии 2
|
||||
([skeletons.md](skeletons.md), раздел `docs/adr/template.md`).
|
||||
2. В существующих записях `docs/adr/ADR-*.md`: жирным поля шапки; если статус
|
||||
записан прозой или заголовком — перенести его полем `- **Статус:**` в шапку
|
||||
и сверить с колонкой «Статус» таблицы в `docs/adr/README.md`.
|
||||
3. `docs/.pm.json`: `"canon": 2`.
|
||||
|
||||
## Версия 1 — 2026-08-03
|
||||
|
||||
Первая версия. Проект любой прежней раскладки приводится к ней скиллом `canon`
|
||||
в режиме `adopt`, а не `upgrade`.
|
||||
|
||||
**Что вводится:** раскладка целиком — см. [canon.md](canon.md).
|
||||
|
||||
**Что сделать проекту, который приходит из свободной раскладки:**
|
||||
|
||||
1. `docs/.pm.json` с `{"canon": 1}` и путём миграций, если БД есть.
|
||||
2. Скелет канона целиком; незаполненное — одной честной строкой.
|
||||
3. `docs/specs/` разобрать: поведение — в `openspec/specs/`, обзор — в
|
||||
`docs/architecture.md`, знание о чужих системах — в `docs/research/`.
|
||||
Дубли capability удалить, сверив поимённо.
|
||||
4. `docs/plan.md` → `docs/tasks/PLAN.md`, шаги плана — целями в «порядок».
|
||||
5. `BRIEF.md` → `docs/passport.md`.
|
||||
6. `docs/backlog/` → `docs/tasks/`.
|
||||
7. `docs/review-journal.md` или `docs/review/journal.md` → `docs/review.md`,
|
||||
плюс раздел настройки конвейера.
|
||||
8. `docs/drafts/` растворить: идея → задача `[idea]`, намеренный отказ → ADR,
|
||||
порядок работ → `PLAN.md`.
|
||||
9. `docs/review-brief.md`, если заводился, удалить: его разделы разошлись по
|
||||
документам канона.
|
||||
10. `conventions.md` → `conventions/`, `local-research.md` → `research/`.
|
||||
11. Завести `docs/security.md` с периметром первой строкой и `docs/adr/`.
|
||||
12. В `CLAUDE.md`: severity рядом с каждым инвариантом; семантика гейта (чем
|
||||
краснеет безусловно, где логи, чего в нём нет и кто тогда гоняет дорогое);
|
||||
**имя основной ветки**; запреты с путями; где `testdata` и куда писать
|
||||
временное; **что считается необратимым**; общий станок; ориентир по размеру
|
||||
спринта. Убрать раздел «Процесс», если он пересказывает пайплайн.
|
||||
13. В `openspec/config.yaml` оставить только нужды генерации и ссылки.
|
||||
14. Добавить шаг `docs.py check` в гейт проекта.
|
||||
|
||||
**Копии правил в шаблонах, которые версия 1 уносит в проект** — их правка в
|
||||
каноне обязана появляться здесь отдельной версией:
|
||||
|
||||
| Что копируется | Дом определения |
|
||||
| --- | --- |
|
||||
| форма записи журнала дефектов в `docs/review.md` | `av-dev-code/skills/review/references/review-journal.md` |
|
||||
| правило заведения ADR в `docs/adr/README.md` | [canon.md](canon.md), раздел `adr/` |
|
||||
@@ -0,0 +1,52 @@
|
||||
# Журнал версий формата задач до слияния плагинов
|
||||
|
||||
**Журнал закрыт.** У каталога задач была своя версия, пока плагином его ведал
|
||||
`av-dev-tasks` и ставился он отдельно. Версия теперь одна на всю раскладку —
|
||||
действующий журнал [changelog.md](changelog.md), и переезд числа описан его
|
||||
записью 1.
|
||||
|
||||
Запись ниже не переписана под нынешние имена: она описывает состояние, которое
|
||||
было.
|
||||
|
||||
---
|
||||
|
||||
## Версия 1 — 2026-08-11
|
||||
|
||||
Первая объявленная версия формата. До неё каталог задач версии не имел вовсе:
|
||||
формат менялся, а сказать, к какому его состоянию приведён конкретный проект,
|
||||
было нечем — `tasks.py` о расхождении молчал, и отставший каталог выглядел
|
||||
здоровым ровно до первой команды, которая об него спотыкалась.
|
||||
|
||||
**Что появилось.** Ключ `tasks` в `<каталог задач>/.tasks.json` — целое число,
|
||||
версия формата. Сам файл стал **обязательным**: до сих пор он заводился только
|
||||
ради имён, отличных от умолчания, и проект с умолчаниями жил без него. Версия —
|
||||
не настройка, от которой можно отказаться, поэтому `init` и `adopt apply` теперь
|
||||
пишут файл всегда, а `check` требует числа и сверяет его со своим.
|
||||
|
||||
**Что версия значит, а что нет.** Она отвечает на один вопрос — «по какой записи
|
||||
журнала повышать каталог». Что записи применены **по существу**, из числа не
|
||||
следует: двигают его руками, и соврать им так же легко, как любой другой
|
||||
строкой. `check --fix` недостающее число не приписывает намеренно — это было бы
|
||||
объявлением каталога приведённым к формату, шагов которого никто не делал.
|
||||
|
||||
**Чего в этой записи нет.** Переезды, случившиеся до появления числа, — каталог
|
||||
из `docs/` в корень (канон 11) и отмена спринтов (канон 12) — задним числом сюда
|
||||
не переписаны. Они уже названы журналом канона, и второй перечень тех же шагов
|
||||
разошёлся бы с первым. Версия 1 — это формат на день её появления, что бы
|
||||
проекту ни пришлось пройти до неё.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. **Догнать формат по журналу канона, если каталог отстал.** Признаки известны
|
||||
поимённо: каталог лежит в `docs/tasks/` (канон 11 велит `git mv docs/tasks
|
||||
tasks` и починку относительных ссылок внутри записей), в нём есть `SPRINT.md`
|
||||
или теги `sprint:<слаг>` (канон 12 велит снести файл, вернуть строки в беклог
|
||||
через `check --fix` и расставить порядок грумингом). Ничего из этого нет —
|
||||
каталог уже в сегодняшнем формате, и шаг пропускается.
|
||||
2. **Завести `<каталог задач>/.tasks.json`**, если его нет. Имена частей в него
|
||||
не переписываются: там только то, что отличается от умолчания.
|
||||
3. **Записать версию**: `"tasks": 1` первым ключом.
|
||||
4. `tasks.py check --dir <каталог задач>` — до отсутствия расхождений.
|
||||
|
||||
**Что при этом не трогается.** Записи в `items/`, индексы и `REJECTED.md` не
|
||||
меняются ни строкой: версия 1 объявляет то, что уже есть, а не переделывает его.
|
||||
@@ -1,790 +1,82 @@
|
||||
# Журнал версий канона
|
||||
# Журнал версий раскладки
|
||||
|
||||
Одна запись на версию. Проект знает свою версию из `docs/.docs.json`; `canon
|
||||
upgrade` идёт по записям снизу вверх от версии проекта до текущей и делает то,
|
||||
что в них названо. Записи ниже версии 13 зовут этот файл прежним именем,
|
||||
`docs/.pm.json`, — так и было на день записи, и переписывать историю мы не
|
||||
станем; переименование делает запись 13.
|
||||
|
||||
**Каталог задач этим журналом не повышается.** У него своя версия формата и свой
|
||||
журнал — `references/changelog.md` скилла `av-dev-tasks:tasks`. Записи 8, 11 и 12
|
||||
трогали его в те времена, когда своего числа у него не было; впредь запись канона
|
||||
вправе позвать соседа, но не двигать его версию.
|
||||
Одна запись на версию. Проект знает свою версию из ключа `version` в
|
||||
`.av-dev.toml`; `canon upgrade` идёт по записям снизу вверх от версии проекта до
|
||||
текущей и делает то, что в них названо.
|
||||
|
||||
Правило записи: **что добавилось, что переехало, что удалено, что сделать
|
||||
проекту**. Без последнего пункта запись бесполезна — по ней и работает
|
||||
`upgrade`.
|
||||
|
||||
Версия — целое число. Обратной совместимости у канона нет: есть «приведён» и «не
|
||||
приведён».
|
||||
Версия — целое число. Обратной совместимости нет: есть «приведён» и «не
|
||||
приведён». Версия **одна на всю раскладку** — и на документы канона, и на
|
||||
каталог задач: ведёт их один плагин, и второе число означало бы только вопрос,
|
||||
по какому журналу повышать.
|
||||
|
||||
**До слияния журналов было два**, и нумерация в них своя:
|
||||
[changelog-before-merge.md](changelog-before-merge.md) — канон документов,
|
||||
версии 1–14; [changelog-tasks-before-merge.md](changelog-tasks-before-merge.md) —
|
||||
формат задач, версия 1. Оба **закрыты и не переписаны**: адрес, верный на день
|
||||
записи, там и остался. Проект, отставший от канона 14, идёт сперва по ним, а
|
||||
потом по этому журналу — порядок назван в записи 1.
|
||||
|
||||
---
|
||||
|
||||
## Версия 14 — 2026-08-11
|
||||
## Версия 1 — 2026-08-13
|
||||
|
||||
У ADR стало два законных источника. Прежде запись цитировала только архивный
|
||||
`design.md`, то есть решение, принятое по ходу изменения. Решение, принятое
|
||||
**разведкой** — намеренный отказ, выбор подхода, «проверили и не делаем», — не
|
||||
имеет `design.md` по построению: change по нему не заводится никогда. Триггер
|
||||
канона такое решение ловит («намеренный отказ от очевидного подхода»), а дома у
|
||||
него не было, и оно оседало в записке разведки или в переписке.
|
||||
Три плагина — `av-dev-docs`, `av-dev-tasks` и `av-dev-code` — слились в один,
|
||||
`av-dev`. Раскол делался под раздельную установку: проект мог взять учёт работ
|
||||
без документов канона или конвейер без обоих. Практикой посылка не подтвердилась
|
||||
— подмножество не понадобилось ни разу, — а платился раскол помеченными копиями
|
||||
общих правил и ветками деградации на каждый вызов соседа.
|
||||
|
||||
**Что изменилось.** `adr/` принимает второй источник — записку разведки. Правило
|
||||
«промоут, а не второе сочинение» не тронуто: запись по-прежнему цитирует уже
|
||||
написанное и **называет источник**, изменилось только то, что источников два.
|
||||
Следом сказали то же самое: карта домов, разрез проверки `doc-consistency`, вход
|
||||
и устав самого агента, скелеты `docs/adr/README.md` и `docs/adr/template.md`.
|
||||
**Что переехало в проекте.** Служебных файла было два, стал один:
|
||||
|
||||
**Почему это версия, а не правка текста.** Два следствия уезжают в репозиторий
|
||||
проекта. По карте домов судит агент согласованности — прежняя редакция читала ADR
|
||||
со ссылкой на записку разведки как нарушение; а скелеты `adr/` лежат в проекте
|
||||
файлами и говорят там от имени канона.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Ничего с существующими записями: прежние ADR ссылаются на `design.md`, и это
|
||||
по-прежнему верно.
|
||||
2. **Поднять шапку `docs/adr/README.md`**: «промоут поверх архивного `design.md`»
|
||||
→ «промоут поверх уже написанного», с обоими источниками. Точный текст — в
|
||||
[skeletons.md](skeletons.md), раздел `docs/adr/README.md`.
|
||||
3. **Поднять `docs/adr/template.md`**: строка `- **Источник:**` называет два
|
||||
возможных источника.
|
||||
4. `docs/.docs.json`: `"canon": 14`.
|
||||
|
||||
**Чего делать не надо.** Заводить ADR задним числом по старым разведкам. Запись
|
||||
заводится, когда решение принимается, а не когда о нём вспомнили: сочинённое
|
||||
через полгода обоснование — ровно то «второе сочинение», против которого правило
|
||||
и написано.
|
||||
|
||||
---
|
||||
|
||||
## Версия 13 — 2026-08-11
|
||||
|
||||
Служебный файл канона переименован: `docs/.pm.json` → `docs/.docs.json`. Имя
|
||||
досталось от плагина `av-dev-pm`, который распался на четыре и которого больше
|
||||
нет: файл пережил владельца и указывал в пустоту. Правило простое и теперь
|
||||
соблюдается всеми тремя: **имя служебного файла — имя плагина, который его
|
||||
завёл**, `.docs.json` — канон, `.tasks.json` — задачи, `openspec/config.yaml` —
|
||||
конвейер.
|
||||
|
||||
**Что изменилось.** `docs.py` читает только новое имя. Прежнее он не читает
|
||||
намеренно: два дома для одной версии канона расходятся молча, а тут расхождение
|
||||
стоило бы дорого — по этому числу `upgrade` решает, какие записи применять.
|
||||
Файл под старым именем `check` узнаёт и называет отдельной строкой с готовой
|
||||
командой, а не жалуется на пропажу.
|
||||
|
||||
**Что появилось у соседа.** У каталога задач теперь есть **своя версия
|
||||
формата** — ключ `tasks` в `<каталог задач>/.tasks.json`, — и свой журнал версий
|
||||
в скилле `av-dev-tasks:tasks`. До сих пор её не было вовсе: формат задач менялся
|
||||
записями этого журнала (8, 11, 12), хотя каталог принадлежит другому плагину и
|
||||
ставится без канона документов. Канон это число не двигает.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. `git mv docs/.pm.json docs/.docs.json` — одним коммитом с шагом 2. Содержимое
|
||||
не меняется: ключи те же.
|
||||
2. **Поправить упоминания прежнего имени** в своих файлах — `CLAUDE.md`, гейт,
|
||||
`README.md`, `docs/**`. Битой ссылкой это чаще всего не выглядит (файл
|
||||
служебный, на него ссылаются прозой), поэтому `docs.py check` таких упоминаний
|
||||
не ловит: ищи `grep -rn '\.pm\.json'` по репозиторию.
|
||||
3. **Объявить версию формата задач**, если каталог задач в проекте есть:
|
||||
`<каталог задач>/.tasks.json` с ключом `"tasks": <версия>`. Файла нет вовсе —
|
||||
заведи, он теперь обязателен: версия не настройка, от которой можно
|
||||
отказаться. Какое число ставить и что сделать перед этим, говорит журнал
|
||||
владельца — **позови скилл `av-dev-tasks:tasks`**, здесь этих шагов нет
|
||||
намеренно: второй перечень чужих шагов разошёлся бы с первым.
|
||||
4. Гейт не меняется: шаги те же, версию задач сторожит `tasks.py check`, который
|
||||
в нём уже стоит.
|
||||
5. `docs/.docs.json`: `"canon": 13`.
|
||||
|
||||
**Чего делать не надо.** Ключи в файле не трогаются, документы не переезжают,
|
||||
записи задач не меняются: версия 13 — про имена служебных файлов и про то, кто
|
||||
чью версию двигает.
|
||||
|
||||
---
|
||||
|
||||
## Версия 12 — 2026-08-09
|
||||
|
||||
Спринты отменены. Работа идёт задача за задачей, и замороженный набор перестал
|
||||
что-либо удерживать: он отвечал на вопрос «что делать дальше», а между наборами
|
||||
на этот вопрос не отвечал никто.
|
||||
|
||||
**Что изменилось.** Индексов задач два вместо трёх: `SPRINT.md` упразднён.
|
||||
Приоритет стал тем, чем он и является, — **порядком строк в `BACKLOG.md`**:
|
||||
первая строка секции это то, что делают следующим. Назначает порядок человек,
|
||||
машина его не выводит; двигают его `move --after` и `move --first` с причиной.
|
||||
|
||||
Гейт готовности записи стоял на взятии задачи в спринт — единственном месте, где
|
||||
её судили целиком. Момент нужен и без спринта: теперь это команда
|
||||
`tasks.py ready <слаг>`, и зовёт её тот, кто берёт задачу в работу.
|
||||
|
||||
Ритуал между спринтами (`av-dev-tasks:session`) стал скиллом груминга
|
||||
(`av-dev-tasks:groom`): два вопроса — что сейчас самое важное и что перестало
|
||||
быть важным.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. **Вернуть задачи из набора в беклог и снести `SPRINT.md`.** Порядок такой:
|
||||
`git rm tasks/SPRINT.md`, затем `tasks.py check --dir tasks --fix`. Строки
|
||||
набора после удаления файла становятся бездомными, и `--fix` возвращает их в
|
||||
беклог **в конец своей секции** — с пометкой, что позицию назначает человек.
|
||||
Наоборот делать нельзя: `check` без удалённого файла увидит третий индекс и
|
||||
станет ругаться на него, а не чинить.
|
||||
2. **Снять теги `sprint:<слаг>`** с записей — `tasks.py edit <слаг> --rm-tag
|
||||
sprint:<слаг>`. Тег больше никем не читается, а `check` о нём молчит: он
|
||||
законный свободный тег. Пропущенный вреда не сделает, но и пользы не несёт.
|
||||
3. **Расставить порядок** — первый груминг: `av-dev-tasks:groom`. После шага 1
|
||||
очередь состоит из того, что машина поставила в конец, то есть очереди нет
|
||||
вовсе. Пока порядок не назначен, «что делать дальше» по-прежнему без ответа.
|
||||
4. Поправить упоминания спринта в `CLAUDE.md` проекта, если они были: слот
|
||||
«общий станок» переехал в груминг под именем «что считается сломанным»,
|
||||
ориентир «5–8 задач в спринте» стал ориентиром размера порции разбора.
|
||||
5. `docs/.pm.json`: `"canon": 12`.
|
||||
|
||||
**Чего делать не надо.** `REJECTED.md`, `ROADMAP.md` и файлы `items/` не
|
||||
меняются: спринт жил только в собственном индексе и в тегах.
|
||||
|
||||
---
|
||||
|
||||
## Версия 11 — 2026-08-09
|
||||
|
||||
Каталог задач уехал из `docs/` в корень репозитория. Версия 8 отпустила его из
|
||||
канона — перестала требовать, перестала проверять, — но место он занимал всё то
|
||||
же, `docs/tasks/`. Полдела: каталог, принадлежащий одному плагину, лежал внутри
|
||||
дерева, которым владеет другой. Проекту, поставившему учёт работ без канона
|
||||
документов, приходилось заводить `docs/` ради одной вложенной папки.
|
||||
|
||||
**Что изменилось.** Дом задач — `tasks/` в корне репозитория. `tasks.py` ищет его
|
||||
там первым; `docs/tasks/` и `doc/tasks/` остаются в списке поиска для
|
||||
непереехавших проектов, а `init` заводит только в корне. Настройки — там же,
|
||||
`tasks/.tasks.json`.
|
||||
|
||||
**Что осталось терпимым.** `docs.py` по-прежнему не считает `docs/tasks/` файлом
|
||||
вне канона: непереехавший проект не должен получать выдуманную ошибку вдобавок к
|
||||
этой записи, которая и так велит ему переехать.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. `git mv docs/tasks tasks` — одним коммитом вместе с шагом 2, чтобы ссылки не
|
||||
жили битыми между коммитами.
|
||||
2. **Починить относительные ссылки внутри записей.** Файл `tasks/items/x.md`
|
||||
стал на уровень ближе к корню: `../../passport.md` в теле записи теперь
|
||||
`../docs/passport.md`. Тот же сдвиг у ссылок из индексов. Это самая тихая
|
||||
часть переезда: битая относительная ссылка не мешает `tasks.py check`, её
|
||||
ловит только `docs.py check` и только у документов канона.
|
||||
3. Проверить ссылки **на** задачи снаружи: `CLAUDE.md`, `README.md`, гейт,
|
||||
`docs/review.md`. Путь `docs/tasks/...` в них теперь ведёт в никуда.
|
||||
4. Поправить путь в гейте: `tasks.py check --dir tasks`.
|
||||
5. `docs/.pm.json`: `"canon": 11`.
|
||||
|
||||
## Версия 10 — 2026-08-09
|
||||
|
||||
Проверка формы `config.yaml` ушла к тому, кто файл заводит. Версия 9 перенесла в
|
||||
конвейер настройку OpenSpec и честно назвала остаток: форма и сторож версии
|
||||
остались в `docs.py`, то есть у файла было два плагина — один заводит, другой
|
||||
проверяет. Остаток закрыт.
|
||||
|
||||
**Что появилось.** Скрипт `openspec.py` в скилле `av-dev-code:openspec`, две
|
||||
команды: `check --dir <корень>` — форма в проекте, `form` — сверка слепка с живым
|
||||
OpenSpec. Коды выхода те же, что у `docs.py` и `tasks.py`.
|
||||
|
||||
**Что удалено из `docs.py`.** Константы `OPENSPEC_*`, проверка формы, сторож
|
||||
версии и подкоманда `openspec-form` — 252 строки. Скрипт канона про
|
||||
`openspec/config.yaml` не говорит теперь ничего; `openspec/specs/` он по-прежнему
|
||||
знает, потому что это дом темы `requirements` и часть карты тем.
|
||||
|
||||
**Что стало лучше по дороге.** Адреса `docs/passport.md` и `CLAUDE.md` требуются
|
||||
теперь **только к тем документам, которые в проекте есть**. Прежняя проверка
|
||||
требовала их безусловно, то есть на проекте без канона документов требовала
|
||||
битую ссылку. Теперь отсутствие документа — строка «не проверялось» с указанием,
|
||||
что без канона конвейер работает вслепую.
|
||||
|
||||
**Что осталось за каноном.** Один вопрос, и это не форма: не пересказан ли в
|
||||
`context` документ, у которого есть свой дом. Разрез — утверждение, опровергаемое
|
||||
открытием другого файла, против строки «открой такой-то файл»; машине он не
|
||||
виден, судит агент `doc-consistency`, и `config.yaml` у него во входе.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Заменить в гейте и в скриптах `docs.py openspec-form` на `openspec.py form`.
|
||||
Подкоманды больше нет: прежний вызов упадёт ошибкой употребления (код 2), а не
|
||||
промолчит.
|
||||
2. **Добавить в гейт шаг `openspec.py check`, если проект работает по OpenSpec.**
|
||||
Форму раньше проверял `docs.py check` заодно; теперь он о ней молчит, и без
|
||||
отдельного шага незаменённый пример в `config.yaml` перестанет ловиться. Это
|
||||
главная потеря этого повышения, и она тихая.
|
||||
3. Проект по OpenSpec без установленного `av-dev-code` — форму не проверяет
|
||||
никто. Либо поставить плагин, либо назвать это принятым риском вслух.
|
||||
4. `docs/.pm.json`: `"canon": 10`.
|
||||
|
||||
## Версия 9 — 2026-08-09
|
||||
|
||||
OpenSpec уехал в конвейер. Каталог `openspec/` версией 7 был объявлен слотом
|
||||
канона: `init` его заводил, `adopt` тоже, образец `config.yaml` лежал в скелетах,
|
||||
а отсутствие каталога `docs.py` считал отказом. Разрез был проведён не там. По
|
||||
OpenSpec работает конвейер — без каталога не запускаются ни `opsx:propose`, ни
|
||||
ревью дизайна, ни сверка требований, — а канон документов о нём только
|
||||
высказывался. Проект, которому конвейер не нужен, получал отказ за отсутствие
|
||||
того, чем не пользуется.
|
||||
|
||||
**Что появилось.** Скилл `av-dev-code:openspec`: заводит каталог, заменяет
|
||||
закомментированный пример в `config.yaml` настройкой, объясняет разрез между
|
||||
ссылкой и пересказом. Образец файла переехал туда же — в
|
||||
`references/config-skeleton.md` того скилла.
|
||||
|
||||
**Что изменилось.** `init` и `canon adopt` OpenSpec больше не заводят, а **зовут
|
||||
скилл конвейера**; вызов не разрешился — плагина конвейера нет, и это строка
|
||||
доклада, а не поломка. Отсутствие `openspec/` для `docs.py check` стало
|
||||
неприменимостью вместо отказа: остальные четыре проверки формы идут только при
|
||||
живом каталоге.
|
||||
|
||||
**Что осталось на месте и почему.** Проверка формы `config.yaml` и сторож версии
|
||||
(`docs.py openspec-form`) пока живут в скрипте канона — переносить их значит
|
||||
заводить в конвейере свой скрипт, а этого у него нет ни одного. Разрез названного
|
||||
это не отменяет, но и не завершает: **у файла сейчас два плагина — один заводит,
|
||||
другой проверяет**, и это временное состояние, а не задуманное.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Ничего не переносить: файлы проекта эта версия не двигает. Меняется только то,
|
||||
кто их заводит.
|
||||
2. Проверить, что плагин `av-dev-code` установлен, если проект работает по
|
||||
OpenSpec. Без него `docs.py check` про каталог промолчит — и молчание это
|
||||
законное, так что отсутствие настройки перестанет ловиться само.
|
||||
3. Проект **не** работает по OpenSpec: убедиться, что `openspec/` нет, и
|
||||
перестать держать его пустым ради проверки. Она больше не требует каталога.
|
||||
4. `docs/.pm.json`: `"canon": 9`.
|
||||
|
||||
## Версия 8 — 2026-08-09
|
||||
|
||||
Канон отпустил каталог задач. Плагин `av-dev-pm` расколот на `av-dev-docs`
|
||||
(документы) и `av-dev-tasks` (учёт работ), и каждый теперь ставится сам по себе.
|
||||
Пока владелец был один, `docs/tasks/` числился слотом канона: `docs.py` требовал
|
||||
каталог, звал внутрь чужой скрипт и выдавал его дрейф за свой, а настройки задач
|
||||
жили ключом `tasks` в `docs/.pm.json`. Для проекта, поставившего только документы,
|
||||
всё это — отказ на ровном месте: задач он не ведёт, и требовать их не за что.
|
||||
|
||||
**Что изменилось.** Каталог задач канону не принадлежит; канон резервирует ему
|
||||
место в `docs/` и внутрь не смотрит. `docs.py` больше не проверяет согласованность
|
||||
задач вовсе — это делает `tasks.py` сам, командой своего плагина. Дом настроек
|
||||
каталога задач — `<каталог задач>/.tasks.json`; ключ `tasks` в `docs/.pm.json`
|
||||
читается, только пока своего файла нет, и об этом говорится замечанием.
|
||||
|
||||
**Что удалено.** Проверка `check_tasks` из `docs.py` и ключ `"tasks"` из скелета
|
||||
`docs/.pm.json`.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. Перенести настройки задач: содержимое ключа `"tasks"` из `docs/.pm.json` — в
|
||||
`docs/tasks/.tasks.json` тем же объектом. Ключа в проекте нет (имена файлов
|
||||
и заголовков умолчательные) — переносить нечего, шаг пропускается.
|
||||
2. Удалить ключ `"tasks"` из `docs/.pm.json` после переноса. Оставленный он не
|
||||
читается, и `tasks.py` скажет об этом замечанием на каждом прогоне.
|
||||
3. Проверить, что согласованность задач по-прежнему кто-то гоняет: раньше её
|
||||
тянул за собой `docs.py check`, теперь — только `tasks.py check`. **Если в
|
||||
гейте проекта стоял один `docs.py`, добавить туда второй шаг** — иначе дрейф
|
||||
индексов перестанет ловиться молча, и это самая вероятная потеря на этом
|
||||
повышении.
|
||||
4. Установить оба плагина, если нужны оба: `av-dev-docs` и `av-dev-tasks`
|
||||
вместо прежнего `av-dev-pm`. Прежний из `enabledPlugins` убрать.
|
||||
5. `docs/.pm.json`: `"canon": 8`.
|
||||
|
||||
## Версия 7 — 2026-08-07
|
||||
|
||||
`openspec/` был предпосылкой, о которой канон говорил, но за которой не следил.
|
||||
Каталог назван в раскладке, `openspec/specs/` объявлен домом темы `requirements`,
|
||||
`config.yaml` описан абзацем — а заводил всё это человек руками, и проверялось
|
||||
из перечисленного ничего. Заведение нового проекта проходило мимо: `init`
|
||||
собирал документы канона и оставлял проект без каталога, без которого не работают
|
||||
ни `opsx:propose`, ни ревью дизайна, ни сверка требований.
|
||||
|
||||
Хуже отсутствия оказался файл из коробки. `openspec init` кладёт `config.yaml`,
|
||||
где `context` и `rules` — закомментированный пример на английском. Такой файл
|
||||
читается как настроенный: он есть, он валиден, имя правильное. Работает он как
|
||||
пустой, и узнаётся это по предложению, написанному на другом языке, с
|
||||
capability по имени пакета и без единого `SHALL`.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **`init` заводит OpenSpec сам** — `openspec init --tools claude`, до первого
|
||||
документа канона. Команда названа в каноне поимённо, потому что её печатает
|
||||
отказ `docs.py`.
|
||||
2. **У `openspec/config.yaml` появилась каноническая форма** и скелет в
|
||||
`skeletons.md`. Содержание — только то, что нужно **в момент порождения
|
||||
артефакта**: язык, правила именования capability, придирки валидатора и
|
||||
**адреса** документов канона. Пересказ паспорта, инвариантов, конвенций и
|
||||
правил ревью в него не переносится.
|
||||
3. **`docs.py check` проверяет пять вещей:** каталог `openspec/` есть; файл
|
||||
называется `config.yaml` (`config.yml` OpenSpec читать не станет и об этом не
|
||||
сообщит); `context` и `rules.specs` не остались примером, а правила для
|
||||
`specs` называют `SHALL`; `context` называет `passport` и `CLAUDE.md`; ключи
|
||||
под `rules:` — имена артефактов схемы, а не опечатки.
|
||||
4. **За свежестью формы следит машина, а не память.** Схема и перечень
|
||||
артефактов — слепок чужого инструмента; `check` сравнивает `major.minor`
|
||||
установленного OpenSpec с версией, на которой форма сверялась, и при
|
||||
расхождении даёт замечание. Перепроверяет `docs.py openspec-form`, и чинится
|
||||
расхождение **в плагине, а не в проекте**.
|
||||
5. **Шестое проверяет агент.** Отличить ссылку на документ от пересказа документа
|
||||
машина не умеет — это работа `doc-consistency`, и в таблице «Что проверяет
|
||||
машина, а что человек» она стоит строкой.
|
||||
|
||||
**Что переехало:** ничего в раскладке `docs/`. Ни один файл не переименовывается
|
||||
и не перемещается.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Нет `openspec/` — завести: `openspec init --tools claude`. Команда кладёт ещё
|
||||
и `.claude/skills/openspec-*` с `.claude/commands/opsx/*`; это её нормальная
|
||||
работа, удалять их не надо.
|
||||
2. Открыть `openspec/config.yaml` и привести к скелету из
|
||||
[skeletons.md](skeletons.md): блок `context` с языком, правилами именования
|
||||
capability, требованием `SHALL` и **адресами** `docs/passport.md` и
|
||||
`CLAUDE.md`; блок `rules` с четырьмя правилами для `specs`.
|
||||
3. **Вычистить из `context` пересказ.** Инварианты, перечень конвенций, состав
|
||||
шагов гейта, правило выбора метки и состав проходов ревью — заменить ссылкой
|
||||
на дом. Признак пересказа простой: строку можно опровергнуть, открыв другой
|
||||
файл проекта.
|
||||
4. Проверить имя файла: `config.yml` переименовать в `config.yaml`. Если жили оба
|
||||
— содержимое `.yml` до сих пор не читалось никем, и переносить из него нужно
|
||||
именно то, чего нет в `.yaml`.
|
||||
5. `docs/.pm.json`: `"canon": 7`.
|
||||
|
||||
---
|
||||
|
||||
## Версия 6 — 2026-08-07
|
||||
|
||||
Версия 5 объявила: **каждый документ `docs/` — тема ревью**. Правило оказалось
|
||||
верным ровно наполовину и потому вредным целиком. Паспорт и схему хранилища
|
||||
ревью читает, но темами они не являются — они задают границу, по которой судит
|
||||
чужая тема. Журнал решений и журнал наблюдений ревью изменения не нужны вовсе:
|
||||
ADR объясняет прошлое решение, а не предъявляет требование к изменению.
|
||||
|
||||
Разметчик, применявший плоское правило буквально, обязан был либо завести
|
||||
фантомные темы `passport`, `adr`, `database`, `research` и продублировать ими
|
||||
работу тем `architecture` и `operations`, либо потерять четыре документа молча —
|
||||
а молчащая потеря и есть то, против чего канон написан.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **Три категории документов вместо одной.** Разрез проверяемый: можно ли по
|
||||
документу сказать «в этом изменении сделано не так»? **Тема** — да, прямо
|
||||
(`conventions`, `security`, `architecture`, свои документы проекта).
|
||||
**Источник темы** — нет, но он задаёт границу для чужой темы (`passport.*` →
|
||||
`architecture`, `database.*` → `operations`, `CLAUDE.md` → `autotests`,
|
||||
`openspec/specs/` → `requirements`). **Процессный документ** — нет, он про то,
|
||||
как мы работаем (`tasks/`, `review.*`, `adr.*`, `research.*`, `.pm.json`).
|
||||
2. **Категории `источник` и `процессный` закрыты, категория `тема` открыта.**
|
||||
Прежде открытым был весь список, и «не темы ровно две» противоречило
|
||||
собственной раскладке канона. Теперь пополняется только одно множество, и
|
||||
документ, которого нет в раскладке, — однозначно своя тема проекта.
|
||||
3. **`adr/` и `research/` уходят из входа ревью изменения.** Прогон их больше не
|
||||
открывает. Проверяться они не перестали: ADR без ссылки на архивный
|
||||
`design.md`, замена без парного статуса, число без провенанса — это по-прежнему
|
||||
работа `doc-consistency` и `doc-code-drift`, на сессии между спринтами.
|
||||
4. **`docs.py` печатает категорию в отказе.** «Нет источника passport» читается
|
||||
иначе, чем «нет темы security». Обязательность при этом не изменилась:
|
||||
заводятся все документы одинаково и с первого дня.
|
||||
5. **У задачи появилась метка — `small`, `medium` или `large`.** Это итог
|
||||
классификации и **единственный вход, по которому конвейер выбирает
|
||||
исполнителей** на обеих стадиях ревью. Прежние имена `quick`, `standard` и
|
||||
`wide` описывали глубину прогона, то есть свойство ревью; метка описывает
|
||||
**задачу** — а выбирают по ней одно и то же. Слово «ступень» уходит:
|
||||
у одной вещи одно имя.
|
||||
6. **Метка выводится из двух осей и не равна ни одной из них.** Размер (малое,
|
||||
среднее, крупное) и сложность (знакомое, незнакомое); метка — максимум по
|
||||
ним. Малое **незнакомое** изменение получает `large`, трогая один узел, —
|
||||
поэтому размер и метка пишутся отдельными строками, и выводить одно из
|
||||
другого нельзя.
|
||||
|
||||
**Цена, записанная явно:** расхождение изменения с записанным решением прогоном
|
||||
больше не ловится. Раньше архитектурный проход мог сказать «здесь отменено
|
||||
решение ADR-2026-03-11, парного статуса нет»; теперь это скажет только сверка
|
||||
документации. Сделка сознательная: чтение всего каталога решений оплачивалось на
|
||||
каждой задаче, а срабатывало на единицах.
|
||||
|
||||
**Что переехало:** ничего в раскладке. Ни один файл не переименовывается и не
|
||||
перемещается.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. `docs/review.*`, подраздел «Вопросы по темам»: убрать вопросы, адресованные
|
||||
`passport`, `database`, `adr`, `research` и `review` — **ни одно из этих имён
|
||||
больше не тема**. Под каноном 5 темой был каждый документ `docs/`, поэтому
|
||||
такие вопросы там законны и почти наверняка есть. Переадресовать:
|
||||
про границу домена и про решение → `architecture`; про хранилище, настройку и
|
||||
измеренное число → `operations`. Вопрос, который никуда не переадресовывается,
|
||||
удалить, а не оставить висеть: адресованный несуществующей теме, он не
|
||||
задаётся никем и молча.
|
||||
2. Там же, «Недоступно проверке»: те же пять имён убрать из разнесения по темам,
|
||||
переразнеся содержимое по оставшимся.
|
||||
3. Там же: подраздел **«Триггеры профиля» → «Триггеры метки»**, и разнести его
|
||||
на **три** списка вместо двух — «крупное здесь» (про объём), «незнакомое
|
||||
здесь» (про форму решения) и «мелкое здесь» (опускает до `small`). Раньше
|
||||
первые две оси были склеены в один список, и потому объём в правило по факту
|
||||
не входил.
|
||||
4. **Переименовать метки прогона везде, где проект их называет** — в «Триггерах
|
||||
метки», в «Недоступно проверке», в журнале дефектов: `quick` → **`small`**,
|
||||
`standard` → **`medium`**, `wide` → **`large`**. Метка это итог классификации
|
||||
задачи, и три её значения — часть общего словаря канона и конвейера. Слово
|
||||
«ступень» из документов уходит: у одной вещи одно имя.
|
||||
5. Проверить, что свои темы проекта не совпадают именем с закрытыми категориями:
|
||||
`docs/passport/`, `docs/adr/`, `docs/research/`, `docs/database/`,
|
||||
`docs/review/` — это слоты канона, а не свои темы, и своим смыслом их
|
||||
наполнять нельзя.
|
||||
6. Ничего не заводить и не удалять: раскладка канона 6 совпадает с раскладкой
|
||||
канона 5 файл в файл.
|
||||
7. `docs/.pm.json`: `"canon": 6`.
|
||||
|
||||
---
|
||||
|
||||
## Версия 5 — 2026-08-06
|
||||
|
||||
Канон перестал быть списком файлов и стал **списком тем ревью**. Раскладка та же,
|
||||
но читается иначе: документ в `docs/` — это направление проверки, а не просто
|
||||
текст. Отсюда три правки, и все три развязывают то, что раньше было жёстко
|
||||
сцеплено.
|
||||
|
||||
**Что изменилось:**
|
||||
|
||||
1. **Тема живёт файлом или каталогом, на выбор проекта.** `docs/security.md` и
|
||||
`docs/security/` — одно и то же; тема разрослась, стала каталогом с
|
||||
`README.md` — канон не сменился и версия не двинулась. Прежде форма была
|
||||
задана поимённо: `conventions`, `research` и `adr` обязаны были быть
|
||||
каталогами, остальные — файлами, и обосновать это было нечем. Обе формы сразу
|
||||
— ошибка: два дома для одного факта расходятся молча.
|
||||
2. **Список тем открытый.** Всё, что проект кладёт в `docs/`, становится темой
|
||||
ревью и попадает в план каждого прогона; именной оптики у такой темы нет, её
|
||||
разбирает общий проход конвейера, заведённый ровно за этим.
|
||||
Прежде `docs.py` называл незнакомый файл «вне канона» — теперь называет своей
|
||||
темой проекта и перечисляет их в отчёте. Не темы ровно две: `docs/tasks/` и
|
||||
`docs/review.*`.
|
||||
3. **`AGENTS.md` рядом с `CLAUDE.md` — законно.** Он почти стандарт; обязателен
|
||||
по-прежнему только `CLAUDE.md`, но если лежат оба, читаются оба, и проверки
|
||||
канона смотрят на второй так же, как на первый.
|
||||
|
||||
**Что переехало:**
|
||||
|
||||
- в `docs/review.*`: **«Вопросы к проходам» → «Вопросы по темам»**, форма
|
||||
`<тема>: <вопрос> (<провенанс>)`. Причина не косметическая: вопрос,
|
||||
адресованный проходу, перестал задаваться молча в тот день, когда тот уехал в
|
||||
верхнюю ступень ревью. Тема переезд прохода переживает, имя прохода — нет;
|
||||
- там же **«Недоступно проверке» — по темам**, оба подраздела.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Ничего не переименовывать, если всё уже разложено по канону 4: обе формы
|
||||
дома законны, и текущая — одна из них.
|
||||
2. `docs/review.*`, подраздел «Вопросы к проходам»: переименовать в «Вопросы по
|
||||
темам» и переадресовать каждый вопрос теме вместо имени прохода. Темы ядра —
|
||||
`requirements`, `autotests`, `conventions`, `architecture`, `security`,
|
||||
`operations`.
|
||||
3. Там же «Недоступно проверке»: разнести обе половины по темам.
|
||||
4. Проверить, не лежит ли в `docs/` документ, который раньше считался лишним и
|
||||
потому не заводился. Теперь он законен и станет темой ревью — это и есть
|
||||
способ добавить проверку, которой в конвейере нет.
|
||||
5. `docs/.pm.json`: `"canon": 5`.
|
||||
6. Позвать судей `doc-consistency` и `doc-code-drift` — шагом 6 `upgrade`.
|
||||
|
||||
## Версия 4 — 2026-08-05
|
||||
|
||||
Две правки, обе про то, как читается каталог задач. Первая — секция роадмапа
|
||||
переименована, и вместе с именем расширен её смысл; достигнутое переехало вниз.
|
||||
Вторая — **у каждой записи появился тип, и тип определяет, что с записью можно
|
||||
делать**. Раскладка не меняется, файлов канона не прибавляется.
|
||||
|
||||
**Что переехало:**
|
||||
|
||||
- секция роадмапа `Разработка` → **`Сопровождение`** (англ. `Tooling` →
|
||||
**`Operations`**). Прежнее имя называло слишком много: роадмап **весь** про
|
||||
разработку, и секция с таким именем не отличалась от остальных ничем;
|
||||
- **тип записи** — из префикса заголовка (`[goal]`/`[idea]`) и тега
|
||||
`kind:<род>` в **поле меты `Тип`** первой строкой. Эмодзи в заголовке от него
|
||||
производна;
|
||||
- **поле места** у задачи: `Секция` → **`Категория`**. У цели остаётся `Секция`:
|
||||
у задачи поле называет полку домена, в которую она вернётся из спринта, у цели
|
||||
— часть роадмапа, то есть состояние очереди. Одно имя на два смысла их и
|
||||
смешивало.
|
||||
|
||||
**Что добавилось:**
|
||||
|
||||
1. **Смысл секции расширен.** Было «инструмент и процесс», стало «чем держат
|
||||
проект: инструмент, процесс, эксплуатация». Метрики, логи, инфраструктура,
|
||||
выкладка и дежурство — сюда же. Расширение не косметическое: английское
|
||||
`Operations` при узком смысле обещало бы эксплуатацию, а внутри лежал бы
|
||||
линтер.
|
||||
2. **Общий словарь трёх мест** — [canon.md](canon.md), раздел «Сопровождение и
|
||||
эксплуатация». Сопровождение — всё, чем держат проект; эксплуатация — его
|
||||
часть, работа системы на проде. `ROADMAP.md`, секция `Сопровождение` — план
|
||||
работ; `architecture.md`, раздел «Эксплуатация» — как устроено сейчас;
|
||||
эксплуатационный проход ревью — оптика проверки. Слить их в одно слово
|
||||
нельзя: они отвечают на разные вопросы. Слово **«поддержка» не употребляется
|
||||
вовсе** — в нём слышится помощь пользователю.
|
||||
3. **Граница с возможностями проходит по тому, кто наблюдает.** «Приложение
|
||||
сообщает о своём состоянии» — возможность приложения, её место среди прочих
|
||||
целей. «Дежурный видит состояние на одном экране» — сопровождение. Одни и те
|
||||
же метрики попадают в разные секции роадмапа, и это верно.
|
||||
4. **Порядок секций стал каноническим**, и `Готово` переехало **вниз**:
|
||||
`Запланировано` | `Направления` | `Сопровождение` | `Готово`. Достигнутое
|
||||
копится — через год этой секции больше, чем всех остальных вместе, — и стоя
|
||||
первой она отодвигает за экран то, ради чего роадмап открывают чаще всего.
|
||||
Порядок проверяет `tasks.py check`, переставляет `check --fix`.
|
||||
5. **Заголовок секции отбивается пустой строкой с обеих сторон.** Прежде
|
||||
проверялась только строка после заголовка; перестановка секций двигает целые
|
||||
блоки, и два заголовка оказываются вплотную. Правит `check --fix`.
|
||||
6. **Тип — единственная ось записи, закрытый словарь из пяти значений:**
|
||||
`goal` | `feature` | `fix` | `chore` | `research`. Осей было две — тип записи
|
||||
(`goal`/`idea`/`task`) и род работы (`kind:` тегом), — но из двенадцати
|
||||
клеток произведения законны были шесть, а алгоритм работы крепится к роду, а
|
||||
не к типу. Оси схлопнуты.
|
||||
7. **Тип задаёт схему тела:** какие разделы обязательны, какие допустимы, нужна
|
||||
ли цель, берётся ли запись в спринт. Проверяет `sprint take`, замечания даёт
|
||||
`check`. Два раздела новые: **`Воспроизведение`** у `fix` (не
|
||||
воспроизводится — это `research`, а не `fix`; правило было записано и не
|
||||
проверялось) и **`Вопрос` + `Куда ляжет ответ`** у `research` вместо
|
||||
критериев приёмки (приёмка разведки — записанный ответ, и критерии в форме
|
||||
«оракул: тест» ей натянуты).
|
||||
8. **Тип `idea` упразднён.** Он значил не род работы, а состояние
|
||||
незаполненности, а состояние типом быть не может. Теперь оно называется
|
||||
честно: `research` без раздела «Вопрос» — **сырьё**. В спринт не берётся, как
|
||||
и прежняя идея, лежит **в конце своей категории** (проверяет `check`,
|
||||
переставляет `--fix`) и отбирается `list --raw`. Порядка «по важности» в
|
||||
беклоге по-прежнему нет: этот порядок производен от типа, а не назначен
|
||||
человеком.
|
||||
9. **Алгоритм работы над каждым типом** — отдельным файлом,
|
||||
`skills/tasks/references/task-<тип>.md`: схема, что проверяет машина, что
|
||||
человек, и порядок шагов.
|
||||
10. **Имена файлов проверяются.** Правило «текст русский, имена английские»
|
||||
стояло в каноне и не было подкреплено ничем: `docs.py` имён не смотрел вовсе.
|
||||
Теперь смотрит — кириллица и не-kebab-case **жёстко**, форма имени
|
||||
`ADR-ГГГГ-ММ-ДД-slug.md` жёстко, транслит **эвристикой**, то есть
|
||||
замечанием. Заодно из раскладки канона убраны плейсхолдеры `<тема>.md`,
|
||||
приглашавшие называть файлы по-русски.
|
||||
11. **Два агента вместо обещания.** В каноне была таблица «Что проверяет машина,
|
||||
а что человек», и её правая колонка три версии описывала судью, которого не
|
||||
существовало. Судьи заведены и разведены по глубине: **`doc-consistency`**
|
||||
(документ ↔ документ ↔ openspec: факт в двух домах, прямое противоречие,
|
||||
поведение в `architecture.md` вместо спек, ADR без ссылки и парного статуса,
|
||||
число без провенанса, заглушка вместо честной строки); **`doc-code-drift`**
|
||||
(документ ↔ код по закрытому перечню фактов). Оба зовутся раз в спринт на
|
||||
сессии, а также после adopt и после upgrade, на весь канон разом.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Переименовать заголовок секции в `docs/tasks/ROADMAP.md`: `## Разработка` →
|
||||
`## Сопровождение` (или `## Tooling` → `## Operations`, если индекс
|
||||
английский). **`check --fix` этого не сделает**: регистр канонической секции
|
||||
он правит сам, а чужую секцию только называет ошибкой — смысл за человеком.
|
||||
2. Поправить поле `- **Секция:**` в файлах целей, которые в ней лежат. Порядок
|
||||
именно такой: сперва заголовок, потом `python3 tasks.py check --dir
|
||||
docs/tasks` покажет расхождение поимённо.
|
||||
3. Перечитать состав секции: цели про выкладку, метрики, логи и инфраструктуру,
|
||||
если они лежали в `Направлениях` за неимением места, переезжают сюда.
|
||||
4. Прогнать `python3 tasks.py check --dir docs/tasks --fix`. За один проход он
|
||||
переставит секции роадмапа в канонический порядок (`Готово` уедет вниз вместе
|
||||
со всем содержимым), поправит отбивку заголовков и **переведёт записи на
|
||||
типы**: перенесёт значение из тега `kind:` и префикса `[goal]`/`[idea]` в поле
|
||||
`Тип`, снимет тег, поставит эмодзи в заголовок, переименует `Секция` →
|
||||
`Категория` у задач и снесёт сырьё в конец категорий.
|
||||
5. Разобрать то, что `--fix` вернул пометкой `НЕОДНОЗНАЧНО`. Главный случай —
|
||||
**записи без типа**: заведённые до появления рода работы, они не несут ни
|
||||
тега, ни префикса, и машина их не угадывает (`feature` от `chore` не
|
||||
отличает). Проставить руками: `edit <слаг> --type …`.
|
||||
6. Дописать новые обязательные разделы у задач, которые собираются в спринт:
|
||||
`Воспроизведение` у каждого `fix`, `Вопрос` и `Куда ляжет ответ` у каждого
|
||||
`research`. Не «заодно по всему беклогу», а порциями переоценки: `check`
|
||||
ошибкой это не считает, отказывает только `sprint take`. Сколько задач готово
|
||||
к взятию, печатает блок здоровья `check`.
|
||||
7. Прогнать `python3 docs.py check`: он назовёт имена файлов не по правилу.
|
||||
Кириллицу и не-kebab-case править обязательно, транслит — по решению
|
||||
человека. **Переименование ADR это перенос ссылок**: слаг стоит в
|
||||
`adr/README.md`, в `architecture.md` и в чужих документах, и делается одним
|
||||
проходом, иначе останутся битые ссылки (их `docs.py` потом и покажет).
|
||||
8. `docs/review.md`, подраздел «Триггеры профиля» — переписать целиком, он
|
||||
отстал дважды. Снести перечень мест для `deep`: профиль упразднён вместе с
|
||||
проходом независимой реализации, и перечень стал указателем в пустоту.
|
||||
Оставшийся перечень перевести на новое правило: `wide` теперь означает не
|
||||
«новое понятие», а **крупное или незнакомое** изменение и рассчитан на 5–10%
|
||||
задач; отдельным списком назвать, что здесь считается **мелким** (это `quick`).
|
||||
Форма подраздела — в [skeletons.md](skeletons.md). Там же проверить журнал
|
||||
дефектов и «Недоступно проверке» на упоминания независимой реализации: класс
|
||||
«форма решения, где спека выбора не сделала» переезжает в подраздел «перестали
|
||||
проверять сознательно», а рядом с ним встаёт вторая честная строка — на
|
||||
`quick` и `standard` не проверяется ничего, что требует запуска.
|
||||
9. `docs/.pm.json`: `"canon": 4`.
|
||||
10. Позвать **обоих судей** — `doc-consistency` и `doc-code-drift`, шагом 6
|
||||
`upgrade`. Пунктов выше десять, половина из них ручная, и именно здесь видно,
|
||||
какие сделаны только наполовину: переименования секций и полей разводят
|
||||
документы, а `check` сверяет число версии, а не существо. Первый прогон на
|
||||
живом проекте вдобавок самый урожайный — правило единственного дома до сих пор
|
||||
никто не проверял. Разбирать порциями, а не одним заходом.
|
||||
|
||||
## Версия 3 — 2026-08-04
|
||||
|
||||
Роадмап стал **состоянием проекта**, а не очередью работ: цель — возможность
|
||||
приложения, задача — шаг к ней, достигнутое из роадмапа не исчезает. Плюс род
|
||||
работы, раздел «Затрагивает» и новое умолчание профиля ревью. Раскладка меняется
|
||||
в одном файле, но переименование и смена секций тянут за собой ссылки, поэтому
|
||||
шаги делаются одним заходом.
|
||||
|
||||
**Что добавилось:**
|
||||
|
||||
1. **Род работы** — тег `kind:<род>` в мете задачи, словарь закрыт:
|
||||
`feature` | `fix` | `chore` | `research`. Обязателен у задачи, у цели
|
||||
запрещён. `sprint take` без него отказывает, `check` о пропаже напоминает
|
||||
замечанием. Определение — [canon.md](canon.md), раздел `tasks/`; смысл и
|
||||
причина, почему тегом, — в SKILL.md скилла `tasks`, раздел «Род работы».
|
||||
2. **Раздел «Затрагивает»** в теле задачи — перечень границ, которых изменение
|
||||
касается (эндпоинт, таблица и миграция, формат на диске, публичный тип). Как
|
||||
и критерии приёмки, требуется к взятию в спринт, а не к заведению.
|
||||
3. **Секции роадмапа** — четыре вместо двух и **канонические**, в отличие от
|
||||
секций беклога: `Готово` (достигнутые цели строкой с датой, без ссылки на
|
||||
файл), `Запланировано` (очередь значима), `Направления` (очереди нет),
|
||||
`Разработка` (инструмент и процесс, не возможности приложения). Английский
|
||||
вариант — `Done` | `Planned` | `Directions` | `Tooling`, один язык на весь
|
||||
индекс. Переименованию проектом не подлежат: у каждой свой смысл, и в первую
|
||||
пишет сам `close`; `tasks.py check` проверяет состав.
|
||||
4. **Форма заголовка записи** — по типу: задача отвечает на «что нужно сделать»
|
||||
и пишется глаголом в неопределённой форме («Не отбрасывать молча лишние
|
||||
символы»), цель — на «что приложение будет уметь», идея просто называет, о
|
||||
чём она. `check` считает заголовки не в форме действия и печатает число в
|
||||
блоке здоровья. Годность формулировки — не машине: её смотрит новый агент
|
||||
`task-form` (форма записи, только чтение), а язык текста — `doc-wording`.
|
||||
5. **Заголовки секций — с прописной, после заголовка пустая строка**, во всех
|
||||
индексах. Написание канонических секций и отбивку правит `check --fix`; он
|
||||
же сводит написание секции в мете файла с заголовком индекса.
|
||||
6. **Язык проектных текстов** — [language.md](language.md), общий дом для
|
||||
документов канона, задач, решений ADR и записок разведки: информационный
|
||||
стиль (глагол вместо отглагольного существительного, активный залог, факт
|
||||
вместо оценки, стоп-слова, параллельность), таблицы англицизмов и жаргона и
|
||||
то, что из стиля отброшено намеренно. Проектных файлов не добавляет и
|
||||
раскладку не меняет — это правила письма, а не новый слот.
|
||||
7. **Умолчание профиля ревью сменилось** — это не раскладка, но проектный текст
|
||||
под него уже написан. `standard` стал рабочим умолчанием: миграция схемы,
|
||||
публичный контракт и инвариант ступень больше **не** поднимают, `wide`
|
||||
означает новое понятие или структурную единицу. Подраздел «Триггеры профиля»
|
||||
в `docs/review.md` остаётся на месте, но его содержимое надо перечитать.
|
||||
|
||||
**Что переехало:** `docs/tasks/PLAN.md` → `docs/tasks/ROADMAP.md`; достигнутая
|
||||
цель — из небытия в секцию `Готово`: `close <цель> --implemented` удаляет файл, но
|
||||
**оставляет строку с датой**. Прежде роадмап отвечал только «что осталось», и
|
||||
половину его вопроса вели прозой руками. Вместе с
|
||||
файлом переименован ключ конфига `tasks.plan` → `tasks.roadmap` и токены
|
||||
команд: `--index plan` → `--index roadmap`, `init --plan-sections` →
|
||||
`--roadmap-sections`, `init --plan` → `--roadmap`. Старый ключ в
|
||||
`docs/.pm.json` не игнорируется молча — `tasks.py` останавливается и называет
|
||||
переименование.
|
||||
|
||||
**Что удалено:** тип `[epic]`. Он был зонтиком между целью и задачами; зонтиком
|
||||
стала цель, а слишком крупный шаг дробится на шаги помельче под ней. Ноль
|
||||
употреблений на 97 записей двух живых проектов.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. `git mv docs/tasks/PLAN.md docs/tasks/ROADMAP.md`.
|
||||
2. Починить ссылки на прежнее имя: `grep -rn 'PLAN\.md' docs/ CLAUDE.md` —
|
||||
заголовок самого файла («# План» → «# Роадмап»), строка в `docs/tasks/BACKLOG.md`,
|
||||
упоминания в `docs/passport.md` и в телах задач.
|
||||
3. `docs/.pm.json`: ключ `tasks.plan`, если он там был, — в `tasks.roadmap`.
|
||||
4. Проставить род работы живым задачам: `python3 tasks.py check --dir docs/tasks`
|
||||
перечислит те, у кого его нет. Задним числом весь беклог не переоформляется —
|
||||
род нужен к взятию, так что порядок такой: сперва то, что берётся в ближайший
|
||||
спринт, остальное по ходу переоценки.
|
||||
5. Дописать раздел «Затрагивает» — тем же порядком и по той же причине: сперва
|
||||
набор спринта, остальное по мере того, как задача попадает в работу.
|
||||
6. Перечитать «Триггеры профиля» в `docs/review.md`: строки вида «миграция →
|
||||
`deep`» теперь дублируют умолчание с обратным знаком. Оставить там только то,
|
||||
что для этого проекта считается **новым понятием** и **правилом
|
||||
идентичности**, — и убрать остальное, иначе проект возвращает себе прежнюю
|
||||
частоту полного набора уточнением.
|
||||
7. Переименовать секции роадмапа: `порядок` → `Запланировано`, `темы` →
|
||||
`Направления`; завести `Готово` **первой** и `Разработка` последней
|
||||
(порядок секций поменялся в версии 4 — если едешь сразу на неё, заводи
|
||||
`Готово` последней и не переставляй дважды).
|
||||
Прозаические разделы вроде «Что уже пройдено», которые велись руками,
|
||||
разложить: звенья — строками в `Готово` (дата, слаг, что стало возможно),
|
||||
обоснование очереди оставить прозой в `Запланировано`. Любой `##` в индексе
|
||||
проверка считает секцией, и теперь `check` называет чужую секцию ошибкой.
|
||||
8. Переформулировать цели ответом на **«что приложение будет уметь»**: не
|
||||
«Работа со слиянием», а «Исход слияния не зависит от порядка доставки».
|
||||
Свойство поведения — законная цель. Цель, которая не про приложение
|
||||
(процесс, инструмент), переезжает в `Разработка`.
|
||||
9. `[epic]`, если он в проекте заводился: это либо цель, либо набор задач под
|
||||
общей целью. `check` назовёт его неизвестным типом.
|
||||
10. Прогнать `python3 tasks.py check --dir docs/tasks --fix`: он поднимет
|
||||
написание канонических секций, поставит отбивку после заголовков и сведёт
|
||||
секцию в мете файлов с заголовками индексов. Секции беклога проект
|
||||
переименовывает сам — их имена он выбирал, и трогать их скрипт не вправе.
|
||||
11. Переписать заголовки задач в форму действия — по мере того, как задача
|
||||
попадает в работу, а не «заодно»: `check` печатает их число, а `task-form`
|
||||
предложит формулировки на замену пачкой.
|
||||
12. Прочитать [language.md](language.md) — и **ничего не переписывать задним
|
||||
числом**. Правила языка применяются к тому, что пишется и правится сейчас;
|
||||
сплошная вычитка старых документов стоит дороже, чем даёт.
|
||||
13. `docs/.pm.json`: `"canon": 3`.
|
||||
|
||||
## Версия 2 — 2026-08-03
|
||||
|
||||
Шапка записи ADR — мета-блоком общей формы, и у статуса появился объявленный
|
||||
дом. Раскладка не менялась: правка касается одного шаблона.
|
||||
|
||||
**Что добавилось:** поле `- **Статус:**` в шапке `docs/adr/template.md` —
|
||||
`заменено на ADR-…` либо `устарело`, у активной записи поля нет. Правило
|
||||
«старая запись получает статус» было и раньше ([canon.md](canon.md), `adr/`),
|
||||
но места под него шаблон не отводил: каждая запись изобретала своё, а колонка
|
||||
«Статус» таблицы `adr/README.md` брала его оттуда, где он у каждого свой.
|
||||
|
||||
**Что переехало:** поля `Дата` и `Источник` в шаблоне стали жирными
|
||||
(`- **Дата:**`, `- **Источник:**`) — та же форма, что у меты задачи и у записи
|
||||
журнала дефектов: поле на строку, имя жирным.
|
||||
|
||||
**Что удалено:** ничего.
|
||||
|
||||
**Что сделать проекту:**
|
||||
|
||||
1. Привести `docs/adr/template.md` к скелету версии 2
|
||||
([skeletons.md](skeletons.md), раздел `docs/adr/template.md`).
|
||||
2. В существующих записях `docs/adr/ADR-*.md`: жирным поля шапки; если статус
|
||||
записан прозой или заголовком — перенести его полем `- **Статус:**` в шапку
|
||||
и сверить с колонкой «Статус» таблицы в `docs/adr/README.md`.
|
||||
3. `docs/.pm.json`: `"canon": 2`.
|
||||
|
||||
## Версия 1 — 2026-08-03
|
||||
|
||||
Первая версия. Проект любой прежней раскладки приводится к ней скиллом `canon`
|
||||
в режиме `adopt`, а не `upgrade`.
|
||||
|
||||
**Что вводится:** раскладка целиком — см. [canon.md](canon.md).
|
||||
|
||||
**Что сделать проекту, который приходит из свободной раскладки:**
|
||||
|
||||
1. `docs/.pm.json` с `{"canon": 1}` и путём миграций, если БД есть.
|
||||
2. Скелет канона целиком; незаполненное — одной честной строкой.
|
||||
3. `docs/specs/` разобрать: поведение — в `openspec/specs/`, обзор — в
|
||||
`docs/architecture.md`, знание о чужих системах — в `docs/research/`.
|
||||
Дубли capability удалить, сверив поимённо.
|
||||
4. `docs/plan.md` → `docs/tasks/PLAN.md`, шаги плана — целями в «порядок».
|
||||
5. `BRIEF.md` → `docs/passport.md`.
|
||||
6. `docs/backlog/` → `docs/tasks/`.
|
||||
7. `docs/review-journal.md` или `docs/review/journal.md` → `docs/review.md`,
|
||||
плюс раздел настройки конвейера.
|
||||
8. `docs/drafts/` растворить: идея → задача `[idea]`, намеренный отказ → ADR,
|
||||
порядок работ → `PLAN.md`.
|
||||
9. `docs/review-brief.md`, если заводился, удалить: его разделы разошлись по
|
||||
документам канона.
|
||||
10. `conventions.md` → `conventions/`, `local-research.md` → `research/`.
|
||||
11. Завести `docs/security.md` с периметром первой строкой и `docs/adr/`.
|
||||
12. В `CLAUDE.md`: severity рядом с каждым инвариантом; семантика гейта (чем
|
||||
краснеет безусловно, где логи, чего в нём нет и кто тогда гоняет дорогое);
|
||||
**имя основной ветки**; запреты с путями; где `testdata` и куда писать
|
||||
временное; **что считается необратимым**; общий станок; ориентир по размеру
|
||||
спринта. Убрать раздел «Процесс», если он пересказывает пайплайн.
|
||||
13. В `openspec/config.yaml` оставить только нужды генерации и ссылки.
|
||||
14. Добавить шаг `docs.py check` в гейт проекта.
|
||||
|
||||
**Копии правил в шаблонах, которые версия 1 уносит в проект** — их правка в
|
||||
каноне обязана появляться здесь отдельной версией:
|
||||
|
||||
| Что копируется | Дом определения |
|
||||
| Было | Стало |
|
||||
| --- | --- |
|
||||
| форма записи журнала дефектов в `docs/review.md` | `av-dev-code/skills/review/references/review-journal.md` |
|
||||
| правило заведения ADR в `docs/adr/README.md` | [canon.md](canon.md), раздел `adr/` |
|
||||
| `docs/.docs.json`, ключ `canon` | `.av-dev.toml` в корне, ключ `version` |
|
||||
| `docs/.docs.json`, ключ `migrations` | `.av-dev.toml`, секция `[docs]` |
|
||||
| `<каталог задач>/.tasks.json`, ключ `tasks` | тот же `version`: версия теперь одна |
|
||||
| `<каталог задач>/.tasks.json`, имена частей | `.av-dev.toml`, секция `[tasks]` |
|
||||
|
||||
Корень выбран потому, что он есть у обоих: и у проекта без `docs/`, и у проекта
|
||||
без каталога задач. Формат TOML — ради комментариев: файл лежит в репозитории
|
||||
проекта, и назначение числа читают из него самого, а не из документации плагина.
|
||||
|
||||
**Что переехало в вызовах.** Имена скиллов сменили пространство имён и получили
|
||||
префикс по прежнему плагину: `av-dev-docs:canon` → `av-dev:doc-canon`,
|
||||
`av-dev-docs:init` → `av-dev:doc-init`, `av-dev-docs:docs` → `av-dev:doc-sync`,
|
||||
`av-dev-docs:healthcheck` → `av-dev:doc-healthcheck`, `av-dev-tasks:tasks` →
|
||||
`av-dev:task-track`, `av-dev-tasks:groom` → `av-dev:task-groom`,
|
||||
`av-dev-code:openspec` → `av-dev:code-openspec`, `av-dev-code:resolve` →
|
||||
`av-dev:code-resolve`, `av-dev-code:review` → `av-dev:code-review`.
|
||||
|
||||
**Что сделать проекту.**
|
||||
|
||||
1. **Отставшим сперва прежние журналы.** Версия канона в `docs/.docs.json`
|
||||
меньше 14 — пройди записи до 14 по
|
||||
[changelog-before-merge.md](changelog-before-merge.md), и только потом эту.
|
||||
Иначе повышение объявит приведённым то, чего никто не делал.
|
||||
2. **Завести `.av-dev.toml`** в корне репозитория: `version = 1`, секция
|
||||
`[docs]` с `migrations`, если ключ был, секция `[tasks]` с `dir` и теми
|
||||
именами частей, которые в `.tasks.json` отличались от умолчаний. Комментарии
|
||||
пиши свои — файл читает человек.
|
||||
3. **Удалить `docs/.docs.json` и `<каталог задач>/.tasks.json`.** Прежние имена
|
||||
не читаются: два дома для одной версии расходятся молча. Пока старые файлы на
|
||||
месте, `docs.py check` и `tasks.py check` называют это прежней раскладкой.
|
||||
4. **Переставить плагины.** `av-dev-docs`, `av-dev-tasks` и `av-dev-code`
|
||||
удалить, `av-dev` поставить — команды в README репозитория плагинов.
|
||||
5. **Поправить гейт проекта.** Пути к `docs.py`, `tasks.py` и `openspec.py`
|
||||
сменились вместе с именами каталогов скиллов: `skills/canon/` →
|
||||
`skills/doc-canon/`, `skills/tasks/` → `skills/task-track/`,
|
||||
`skills/openspec/` → `skills/code-openspec/`. Шаг, который не нашёл скрипт,
|
||||
обязан краснеть, а не пропускаться, — проверь, что он краснеет.
|
||||
6. **Поправить свои вызовы скиллов** — в `CLAUDE.md`, в `Taskfile`, в записях
|
||||
задач: короткое имя разрешится в проектную копию, а прежнее полное не
|
||||
разрешится вовсе.
|
||||
7. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия
|
||||
дрейфа.
|
||||
|
||||
**Чего делать не надо.** Переписывать прошлые записи журналов под новые имена.
|
||||
Они описывают состояния, которые были, и адрес, верный на день записи, остаётся
|
||||
верным как свидетельство.
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
со строкой «запись лежит сжатой и распаковывается целиком».
|
||||
```
|
||||
|
||||
Нет БД — файла нет, и в `docs/.docs.json` нет ключа `migrations`.
|
||||
Нет БД — файла нет, и в `.av-dev.toml` нет ключа `[docs] migrations`.
|
||||
|
||||
## `docs/security.md`
|
||||
|
||||
@@ -440,24 +440,32 @@ severity стоит здесь, а не выводится каждым прох
|
||||
говорит (единственный дом, а не форма) — [canon.md](canon.md), раздел
|
||||
`openspec/config.yaml`.
|
||||
|
||||
## `docs/.docs.json`
|
||||
## `.av-dev.toml`
|
||||
|
||||
```json
|
||||
{
|
||||
"canon": <текущая версия>
|
||||
}
|
||||
```toml
|
||||
# Раскладка av-dev в этом проекте: версия и настройки проверок.
|
||||
|
||||
version = <текущая версия>
|
||||
|
||||
[docs]
|
||||
# migrations = "<путь>" — появится, когда появится БД
|
||||
|
||||
[tasks]
|
||||
dir = "tasks"
|
||||
```
|
||||
|
||||
`<текущая версия>` подставляет `init` или `adopt`, целым числом; берётся она из
|
||||
`docs.py version` (строка «канон скрипта»), а не из памяти. Литерал здесь
|
||||
протухает при каждом повышении канона, поэтому его тут и нет: незамещённый
|
||||
плейсхолдер ломает разбор JSON громко, а отставшее число дало бы дрейф молча.
|
||||
`docs.py version` (строка «раскладка скрипта»), а не из памяти. Литерал здесь
|
||||
протухает при каждом повышении, поэтому его тут и нет: незамещённый плейсхолдер
|
||||
ломает разбор TOML громко, а отставшее число дало бы дрейф молча.
|
||||
|
||||
Плюс `"migrations": "<путь>"`, если есть БД. Ключа `"tasks"` здесь **нет**:
|
||||
настройки каталога задач и версия их формата переехали в свой файл `<каталог
|
||||
задач>/.tasks.json`, потому что ведёт их другой плагин. Состав ключей —
|
||||
[canon.md](canon.md).
|
||||
Комментарии в файле — не украшение, а причина, по которой взят TOML: файл живёт
|
||||
в чужом репозитории, и назначение числа читают из него самого. Скрипты это
|
||||
учитывают и правят строку, а не переписывают файл. Состав ключей —
|
||||
[canon.md](canon.md), раздел `.av-dev.toml`.
|
||||
|
||||
Имя файла — по плагину-владельцу, `av-dev-docs`. До версии 13 он звался
|
||||
`.pm.json`, по распавшемуся `av-dev-pm`; проект с прежним именем `docs.py check`
|
||||
называет отдельной строкой и зовёт переименовать.
|
||||
Файл лежит **в корне репозитория**, а не в `docs/`: версия одна на всю
|
||||
раскладку, и нужна она в том числе проекту, который канон документов ещё не
|
||||
завёл. Прежние `docs/.docs.json` и `<каталог задач>/.tasks.json` остались от
|
||||
трёх плагинов, слившихся в один; увидев их, `docs.py check` называет это прежней
|
||||
раскладкой и зовёт `upgrade`.
|
||||
|
||||
Reference in New Issue
Block a user