# Журнал версий канона Одна запись на версию. Проект знает свою версию из `docs/.pm.json`; `canon upgrade` идёт по записям снизу вверх от версии проекта до текущей и делает то, что в них названо. Правило записи: **что добавилось, что переехало, что удалено, что сделать проекту**. Без последнего пункта запись бесполезна — по ней и работает `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/.pm.json`: `"canon": 4`. 9. Позвать **обоих судей** — `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-pipeline/skills/review-pipeline/references/review-journal.md` | | правило заведения ADR в `docs/adr/README.md` | [canon.md](canon.md), раздел `adr/` |