# Журнал версий раскладки Одна запись на версию. Проект знает свою версию из ключа `version` в `.av-dev.toml`; операция `upgrade` скилла `av-dev:canon` идёт по записям снизу вверх от версии проекта до текущей и делает то, что в них названо. Правило записи: **что добавилось, что переехало, что удалено, что сделать проекту**. Без последнего пункта запись бесполезна — по ней и работает `upgrade`. Версия — целое число. Обратной совместимости нет: есть «приведён» и «не приведён». Версия **одна на всю раскладку** — и на документы канона, и на каталог задач: ведёт их один плагин, и второе число означало бы только вопрос, по какому журналу повышать. **До слияния журналов было два**, и нумерация в них своя: [changelog-before-merge.md](changelog-before-merge.md) — канон документов, версии 1–14; [changelog-tasks-before-merge.md](changelog-tasks-before-merge.md) — формат задач, версия 1. Оба **закрыты и не переписаны**: адрес, верный на день записи, там и остался. Проект, отставший от канона 14, идёт сперва по ним, а потом по этому журналу — порядок назван в записи 1. --- ## Версия 5 — 2026-08-23 **Метка задачи снята из процесса целиком**, и вместе с ней — подраздел «Триггеры метки» в `docs/review.md`. Состав прогона ревью стал постоянным: он один и тот же на всякой задаче, выбирать нечего, и признаки, по которым метка поднималась, перестали что-либо решать. На месте подраздела — **«Когда звать глубокое ревью»**: те же наблюдения проекта, но адресованные другому решению — звать ли `av-dev:code-deep-review` по области кода. **Что переехало в проекте.** Скелет `docs/review.md`, раздел настройки конвейера: подраздел «Триггеры метки» заменён подразделом «Когда звать глубокое ревью» — **двумя списками**: области, которые смотрят целиком (узлы с частым возвратом, места с историей инцидентов, код под дорогое решение), и **необратимое здесь** — что в этом проекте после мерджа не откатывается обратной правкой. Второй список работает и в цикле задачи: находка в таком месте уходит человеку развилкой, а не чинится молча. Само правило — в [canon.md](canon.md), раздел `review.md`. **Что сделать проекту.** 1. **Переписать подраздел в `docs/review.md`.** Заголовок «Триггеры метки» становится «Когда звать глубокое ревью», содержимое — два списка выше. Признаки, годные только для выбора метки («больше N файлов», «затронуто больше одного слоя»), выбрасываются: состава прогона они не меняют. Что из прежнего списка называло **необратимое место** — переносится во второй список дословно. 2. **Пройти по документам** — `grep -rniE "small|medium|large|метк" docs/`. Найденное в `review.md`, `conventions/` и `adr/` правится по смыслу: описание прошлого решения остаётся как свидетельство, действующая инструкция — переписывается или снимается. 3. **Поднять версию** — `docs.py bump`, последним шагом. 4. `docs.py check` — до отсутствия дрейфа. **Чего делать не надо.** Заводить ключ `[docs] healthcheck_last` руками: он необязательный и появится сам первым прогоном `av-dev:doc-healthcheck`. Править прошлые записи журналов и архивные change — тоже: метка, стоявшая в них, верна как свидетельство о том дне. --- ## Версия 4 — 2026-08-13 Слово **провенанс** снято из словаря языка проектных текстов и заменено русским. Оно стояло в закрытом списке своих терминов с оговоркой «„источник“ рядом называет саму запись, а не свойство» — верной, но доказывающей лишь то, что не годится одно русское слово. Годятся два, и по смыслу они разные: **происхождение** у числа (чем и при каких условиях получено) и **откуда** у вопроса или находки (кто нашёл, каким проходом, из какой записи журнала). **Что переехало в проекте.** Скелет `docs/review.md`, подраздел «Вопросы по темам»: форма вопроса записана как `<тема>: <вопрос> (<откуда>)` вместо `(<провенанс>)`. Само правило — в [canon.md](canon.md), раздел `review.*`; требование к числам `research/` не изменилось по существу, изменилось слово. **Что сделать проекту.** 1. **Поправить форму в `docs/review.md`** — строка «Форма: `<тема>: <вопрос> (<провенанс>)`» становится «Форма: `<тема>: <вопрос> (<откуда>)`». Уже записанные вопросы переписывать не надо: слово стояло в шаблоне, а не в них. 2. **Пройти по документам** — `grep -rn "провенанс" docs/`. Найденное в `research/` и в `adr/` заменяется на **происхождение** (речь о числе) или на **откуда** (речь о том, из чего вопрос или находка выросли). Ничего не нашлось — шаг закрыт строкой, это обычный исход. 3. **Поднять версию** — `docs.py bump`, последним шагом. 4. `docs.py check` — до отсутствия дрейфа. **Чего делать не надо.** Править прошлые записи журналов и архивные change: слово, верное на день записи, остаётся верным как свидетельство. --- ## Версия 3 — 2026-08-13 Тип записи `goal` и индекс `ROADMAP.md` упразднены; у проекта появилась **стадия** — `build` (беклог это план стройки, порядок строк значит зависимость) или `support` (очередь правок, порядок значит важность). Цель была зонтиком над параллельными направлениями — она нужна там, где список работ нельзя выстроить в один порядок. У проекта, который ведёт один человек, такого не бывает, и роадмап при этом наполовину дублировал беклог («чего ещё не умеет» = «что осталось в списке»), а вторую половину («что уже умеет») отвечают `openspec/specs/` и `git log` индекса. **Что переехало.** Индекс остался один — `BACKLOG.md`. Поле меты `Секция` стало `Категория`; теги `goal:<слаг>`, `decomposed` и раздел `Завершение` упразднены; команды `list --goal`, `edit --goal`, `edit --section` и ключи `[tasks] roadmap`, `[tasks] completion_heading` — тоже. Появились ключ `[tasks] stage`, команда `tasks.py stage` и флаги `init --stage`, `adopt scan --stage`. **Что сделать проекту. Порядок шагов обязателен**, и первый шаг — не команда: пока в `[tasks]` лежит упразднённый ключ, **любая** подкоманда `tasks.py` отвечает кодом 3 и работать нечем. 1. **Вычистить конфиг руками.** Из секции `[tasks]` в `.av-dev.toml` удалить ключи `roadmap` (или `plan`) и `completion_heading`. Каждый из них — код 3 на любой команде, и названы они здесь оба: второй легко пропустить, потому что его упразднение не видно по имени файла. 2. **Удалить `tasks/ROADMAP.md`.** Секция `Готово` уходит вместе с ним и **не переносится**: «что приложение умеет» отвечают спеки, «когда это появилось» — `git log` беклога. Проект без `openspec/specs/` теряет здесь единственный связный перечень достигнутого — если он нужен, сохрани его сам до удаления (документом проекта, не задачами). 3. **Прогнать `tasks.py check --fix`.** Он снимет теги `goal:<слаг>` и `decomposed`, переименует поле `Секция` → `Категория` и перепишет старую форму меты — **в том числе у самих записей типа `goal`**. Записи `goal` при этом останутся: во что превращается цель, машина не решает и говорит `НЕОДНОЗНАЧНО`. 4. **Разобрать цели поштучно.** У каждой два исхода, и выбирает человек: она становится задачей (`edit <слаг> --type feature|fix|chore|research`) либо уходит (`close <слаг> --reason …`). Строки в беклоге у неё нет — её жильём был роадмап, — и `edit --type` заведёт её сам, в первую секцию и в конец, сказав об этом; место назначь потом. Раздел `Завершение` в теле переехавшей записи **удали руками**: схеме нового типа он не принадлежит, и `check` оставит о нём замечание. Задачи, носившие тег цели, живут дальше сами по себе — разбирать их не нужно. 5. **Объявить стадию** — `tasks.py stage build` или `tasks.py stage support`. Приложение ещё строится и список работ линеен по зависимости — `build`; работает и правится точечно — `support`. Без ключа `check` отказывает: порядок строк нечем прочитать. **Объявление беклог не трогает** — ни секций, ни файлов: оно называет то, что уже верно. Поэтому проекту с несколькими полками, объявляющему `build`, команда откажет и назовёт выход: слить полки самому (`move <слаг> --section <куда> --reason …`), потому что порядок строк в слитом списке знает только человек. Флаг `--sections` при объявлении не принимается — он для **смены** стадии, где сливать просят явно. 6. **Поправить шапку `BACKLOG.md`.** Абзац про стадию теперь размечен парой `` … ``, и по нему `check` сверяет шапку с конфигом. В беклоге, заведённом до этой версии, разметки нет — `stage` об этом скажет. Возьми готовый абзац из свежего каталога (`tasks.py init` во временном месте) или напиши сам: он объясняет, что значит порядок строк, и читают вместо документации именно его. 7. **Поднять версию** — `docs.py bump`. Последним шагом. Он двигает **одну** запись за раз: отставшему на две записи проекту зовётся дважды, следом за шагами каждой. 8. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия дрейфа. **Проект, не прошедший записи 1 и 2, начинает с этой.** Их собственные шаги велят гонять `tasks.py check` до зелёного, а он на упразднённом ключе отвечает кодом 3 — то есть пройти их сегодня нельзя, не сделав шаг 1 отсюда. Записи от этого не переписываются: порядок между ними прежний, добавлено одно условие входа. --- ## Версия 2 — 2026-08-13 Скилл `doc-canon` стал `canon`: префикс называл материал (`doc-`), а скилл занят не материалом, а **формой** — раскладкой всех частей проекта и общим повышением версии. Ни один файл проекта от этого не переехал; сменились **путь к скрипту** и **имя вызова**, а оба живут в проекте: первый — строкой гейта, второй — в `CLAUDE.md` и в записях задач. **Что переехало в вызовах.** `av-dev:doc-canon` → `av-dev:canon`. Прочие имена не тронуты. **Что сделать проекту.** 1. **Поправить шаг гейта.** Путь к `docs.py` сменился вместе с именем каталога скилла: `skills/doc-canon/scripts/docs.py` → `skills/canon/scripts/docs.py`. Шаг, который не нашёл скрипт, обязан краснеть, а не пропускаться, — проверь, что он краснеет. 2. **Поправить свои вызовы скилла** — `grep -rn "doc-canon" --exclude-dir=.git .` по проекту целиком: имя встречается в `CLAUDE.md`, в `Taskfile`, в записях задач и в документах канона. Прежнее полное имя не разрешится вовсе. 3. **Поднять версию** — `docs.py bump`. Последним шагом. 4. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия дрейфа. **Проект, не прошедший запись 1, переименовывает дважды подряд** — `skills/canon/` → `skills/doc-canon/` записью 1 и обратно этой. Порядок записей от этого не меняется: каждая исполняется на том состоянии, которое оставила предыдущая, и прошлая запись под новое имя не переписывается. --- ## Версия 1 — 2026-08-13 Три плагина — `av-dev-docs`, `av-dev-tasks` и `av-dev-code` — слились в один, `av-dev`. Раскол делался под раздельную установку: проект мог взять учёт работ без документов канона или конвейер без обоих. Практика посылку не подтвердила — подмножество не понадобилось ни разу, — а платился раскол помеченными копиями общих правил и веткой «плагина нет» на каждый вызов соседа. **Что переехало в проекте.** Служебных файла было два, стал один: | Было | Стало | | --- | --- | | `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/.docs.json`, чтобы не заводить факту второй дом. Такое чтение переезжает на `.av-dev.toml` и на `tomllib` вместо `json`: `python3 -c 'import tomllib; print(tomllib.load(open(".av-dev.toml","rb"))["docs"]["migrations"])'`. Ищется командой `grep -rn "\.docs\.json\|\.tasks\.json" --exclude-dir=.git .` — по проекту целиком, а не по документам: на первом же живом переезде это нашлось в `Taskfile.yml`, и нашёл это гейт, а не человек. 8. **Поднять версию** — `docs.py bump`. Последним шагом: число объявляет пройденными шаги журнала, и раньше времени поднятое врёт. 9. `docs.py check` и `tasks.py check --dir <каталог задач>` — до отсутствия дрейфа. **Чего делать не надо.** Переписывать прошлые записи журналов под новые имена. Они описывают состояния, которые были, и адрес, верный на день записи, остаётся верным как свидетельство.