From c6be87983131bc747fa9fe021714b2fef4bfaa57 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sun, 9 Aug 2026 15:02:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0=BE=20?= =?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA?= =?UTF-8?q?=20=D1=81=D0=BE=D1=81=D0=B5=D0=B4=D0=BD=D0=B5=D0=BC=D1=83=20?= =?UTF-8?q?=D0=BF=D0=BB=D0=B0=D0=B3=D0=B8=D0=BD=D1=83=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B8=D0=BB=D0=BE=20=D0=B4=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Стояло в пяти местах в пяти редакциях: два разных довода, ни в одном месте оба, и три места из пяти молчали о том, что делать при неразрешившемся вызове. Плюс невысказанный инвариант: $CLAUDE_PLUGIN_ROOT ведёт только в свой плагин. Дом — shared/plugin-boundary.md, блок «граница-плагинов», семь помеченных копий. В дом вошло правило, последствия остались на местах вызова: «нет плагина задач — учёт остаётся владельцу» знает только конвейер. Оглавление адресов в CLAUDE.md проекта отклонено — второй дом раскладки, и протухший адрес в нём выходит правдоподобной строкой честной деградации. Сверка адресов уходит машине, записана в TODO разделом 5. --- DECISIONS.md | 69 +++++++++++++++++++ README.md | 19 +++-- TODO.md | 22 +++++- av-dev-docs/skills/canon/SKILL.md | 42 ++++++++++- av-dev-docs/skills/docs/SKILL.md | 38 ++++++++++ av-dev-docs/skills/init/SKILL.md | 42 ++++++++++- av-dev-pipeline/skills/openspec/SKILL.md | 34 ++++++++- .../skills/review-pipeline/SKILL.md | 40 +++++++++-- av-dev-pipeline/skills/task-batch/SKILL.md | 39 +++++++++-- av-dev-pipeline/skills/task-pipeline/SKILL.md | 39 ++++++++++- shared/plugin-boundary.md | 55 +++++++++++++++ 11 files changed, 413 insertions(+), 26 deletions(-) create mode 100644 shared/plugin-boundary.md diff --git a/DECISIONS.md b/DECISIONS.md index db22a77..8c5b095 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -3299,3 +3299,72 @@ JJJ): у профиля обязан быть один правильный от наоборот — один предмет, разрезанный так, что оба куска нужны одновременно, разрезан неверно. + +## 54. Стык плагинов: правило получило дом, адреса остались у владельцев (2026-08-09) + +**АЕАКМ. Вопрос пришёл с другой стороны: ревью опирается на документы проекта, +но не должно жёстко предполагать, где файл лежит; напрашивалось оглавление +адресов и сводка возможностей скиллов в `CLAUDE.md` проекта.** Отклонено и то и +другое, но не потому, что проблемы нет. + +**Оглавление адресов — второй дом раскладки.** Канон жёсток намеренно: пути +фиксированы, проект подгоняется под них, и цена этого записана в самом каноне. +Указатель в `CLAUDE.md` отменяет ровно эту цену — раскладка получает второе +описание, и разойдутся они молча. Здесь молчание особенно дорогое: прогон ревью +умеет **честно деградировать**, и протухший адрес попадает прямо в эту машинерию — +файл не открылся, в границах покрытия появляется строка «документа в проекте +нет», и отчёт выглядит добросовестным. Прямой путь в той же ситуации ломается +громче. + +**Сводка возможностей — второй дом описаний.** `description` во фронтматтере это +триггер, по нему скилл и выбирается; переписанная руками сводка тех же описаний +не сверяется ничем. + +**Настоящий пробел был в другом, и он измерен.** Правило обращения к соседнему +плагину стояло в пяти местах в пяти редакциях: + +| Где стояло | Довод | Ветка «не разрешился» | +| --- | --- | --- | +| `task-pipeline` | устаревшая проектная копия | нет | +| `task-batch` | то же | нет | +| `review-pipeline` | вшито в пункт про удаление проектных копий | нет | +| `openspec` | путём в чужое дерево — никогда | есть | +| `canon` | — | есть | + +Два разных довода, и ни в одном месте не было обоих; три места из пяти молчали о +том, что делать при неразрешившемся вызове, — то есть о единственном, ради чего +правило написано. Плюс невысказанный инвариант: `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин, употреблён двадцать раз и нигде не оговорён — а именно он +соблазняет дописать `/../av-dev-docs/`. + +**Сделано:** дом `shared/plugin-boundary.md`, блок `граница-плагинов`, семь +помеченных копий — четыре скилла конвейера и три скилла канона. В дом вошли +полное имя, запрет пути в чужое дерево, ветка «не разрешился» с обязанностью +доклада и признак присутствия по заведённому соседом файлу. + +**Разрез, по которому дом наполнялся: правило общее, последствие местное.** «Нет +`av-dev-tasks` — учёт остаётся владельцу» знает только конвейер; «нет конвейера — +`docs.py` о каталоге `openspec/` молчит» знает только канон. Держи дом +последствия — он знал бы наперечёт всех своих потребителей и стал бы вторым +каноном. + +**Адреса при этом наружу не поехали.** У них владелец есть: раскладку `docs/` +держит канон, каталог задач — плагин задач. `shared/` заводится **только для +фактов без владельца**; чужое с владельцем остаётся дома, а сходимость +упоминаний в чужих деревьях проверяется машиной — это следующая работа, записана +в TODO. + +### Что из этого следует + +179. **Механизм честной деградации превращает протухший адрес в правдоподобный + доклад.** Там, где отсутствие источника — законный исход с названной ценой, + ошибка адреса неотличима от этого исхода. Значит адрес в таком месте обязан + сверяться машиной, а не аккуратностью: единственная альтернатива — + ломаться громко, а именно её деградация и убирает. +180. **`shared/` — для фактов без владельца, и только.** У адресов владелец есть, + и вынести их наружу значило бы отобрать у него его же предмет. Признак + верного дома не «нужно нескольким», а «никому из них не принадлежит». +181. **Общее правило и его последствия живут порознь.** Правило можно вынести в + дом, последствие — нет: оно знает про место, а место про правило знать не + обязано. Дом, вобравший последствия, становится реестром потребителей и + устаревает быстрее их всех. diff --git a/README.md b/README.md index 7089bf7..182c51e 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,11 @@ flowchart TB Зависимости **односторонние: `av-dev-pipeline` знает про `av-dev-docs` и `av-dev-tasks`, обратно — нет.** Между собой эти двое тоже не связаны жёстко: -каждый работает без другого и зовёт соседа **через пространство имён**, а не по -пути в чужое дерево. Не разрешился вызов — плагина нет, и это исход, который -проговаривается строкой, а не поломка. То, что нужно обоим дословно — язык -проектных текстов и словарь сопровождения, — живёт домом в `shared/` и уезжает в -каждый плагин помеченной копией. +каждый работает без другого. Как именно зовут соседа и что делают, когда вызов не +разрешился, — `shared/plugin-boundary.md`: правило нужно семи скиллам в трёх +плагинах, и ни один им не владеет. То, что нужно нескольким дословно — граница +плагинов, язык проектных текстов, словарь сопровождения, — живёт домом в +`shared/` и уезжает в каждый плагин помеченной копией. ## Канон документов проекта @@ -337,10 +337,17 @@ uv run python scripts/copies.py # 0 сошлось, 1 расхождение **Дом правила, общего для нескольких плагинов, лежит в `shared/` и ни одному из них не принадлежит.** Так живёт язык проектных текстов: он одинаково нужен документам канона и задачам, и хранить его внутри одного плагина значило бы -отдать общее правило во владение половине. Плагин везёт копию и потому остаётся +отдать общее правило во владение половине. Так же живёт граница плагинов — +правило обращения к соседу. Плагин везёт копию и потому остаётся самодостаточным — `shared/` нужен этому репозиторию, а не установленному плагину. +**Дом ставится в `shared/` только тогда, когда владельца нет.** У адресов +владелец есть: раскладку `docs/` держит канон, каталог задач — плагин задач, и +переносить их наружу значило бы отобрать у владельца его же предмет. Общее без +владельца едет копией из `shared/`; чужое с владельцем остаётся дома, а +потребитель на него ссылается. + Скрипт ловит четыре вещи: копия разошлась с домом (с диффом), копия указывает не на тот файл, дом остался без копий, разметка сломана. Чего он **не** ловит — копию, которую забыли пометить: помечать — по-прежнему решение человека. diff --git a/TODO.md b/TODO.md index 9523083..230fc41 100644 --- a/TODO.md +++ b/TODO.md @@ -110,7 +110,27 @@ сколько из пяти стадий реально смотрятся глазами. 1028 строк, и весь автоматический этап держится на них -## 5. Обкатка +## 5. Стык плагинов — проверка адресов + +Не блокирует ничего и делается после раздела 1: писать чекер лучше, когда +`adopt` на живом проекте покажет, какие адреса называются вслух. Правило +обращения к соседу дом уже получило (`shared/plugin-boundary.md`, решение 54) — +осталась вторая половина. + +- [ ] `scripts/addresses.py`: владелец отдаёт перечень своих адресов машинно + (константа, по которой он и так проверяет раскладку, — `docs.py` и + `tasks.py`), чекер грепает чужие деревья и падает на адресе, которого у + владельца нет. **Зачем машина, а не внимание:** протухший адрес в проходе + ревью попадает в механизм честной деградации и выходит правдоподобной + строкой «документа в проекте нет» (решение 54, вывод 179) +- [ ] форма адреса нормализуется до имени темы: `docs/security.md`, + `docs/security/` и `docs/security.*` — одна запись. Иначе чекер начнёт + требовать выбора формы, которую канон сознательно оставляет проекту +- [ ] упоминание **отставленного** адреса в чужом плагине — тоже находка: + карта RETIRED у `docs.py` уже есть, и сейчас её не сверяет никто. Журнал + версий из проверки исключается — задним числом он не переписывается + +## 6. Обкатка - [ ] один-два цикла healthlog на новом процессе; наблюдение к первой обкатке — не выродились ли «границы покрытия» в шаблон (REMAINING, «Открытые diff --git a/av-dev-docs/skills/canon/SKILL.md b/av-dev-docs/skills/canon/SKILL.md index 46c610b..a5540b5 100644 --- a/av-dev-docs/skills/canon/SKILL.md +++ b/av-dev-docs/skills/canon/SKILL.md @@ -87,6 +87,44 @@ capability: незаполненный канон это переходное с формулировка казалась удачной при написании. Ни один из них ничего не правит — оба возвращают готовые формулировки, подставляешь ты. +## Обращение к соседним плагинам + +`adopt` зовёт двоих: `av-dev-pipeline:openspec` (шаг 4, пункт 3) и +`av-dev-tasks:tasks` (шаг 4, пункт 5). Каталоги `openspec/` и `tasks/` каноном не +ведутся, и трогать их этому скиллу нечем, кроме вызова. + +**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов. +Правится дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Чем оборачивается отсутствие каждого — на самих пунктах шага 4. `adopt` из-за +этого не останавливается ни в одном из двух случаев. + ## `check` 1. `docs.py check`, при наличии базы диффа — с `--base`. @@ -148,8 +186,8 @@ capability), `openspec/config.yaml`. Skill `av-dev-pipeline:openspec`**. Каталог принадлежит конвейеру, и команда заведения с формой файла живут там. Пересказ инвариантов, конвенций и правил ревью из `context` вычисти ссылкой на дом — на переводимом проекте он там - почти наверняка есть. Вызов не разрешился — плагина конвейера нет, и это - строка доклада, а не поломка: `docs.py` о каталоге тогда тоже молчит; + почти наверняка есть. Вызов не разрешился — `docs.py` о каталоге тогда тоже + молчит, и форму `config.yaml` не проверяет никто; скажи это строкой; 4. переносы содержимого; 5. каталог задач — **вызови скилл `av-dev-tasks:tasks`**, сценарий адаптации: он владеет форматом задач. Он же переименует транслитные слаги в английские и diff --git a/av-dev-docs/skills/docs/SKILL.md b/av-dev-docs/skills/docs/SKILL.md index 79dd02e..bb3db16 100644 --- a/av-dev-docs/skills/docs/SKILL.md +++ b/av-dev-docs/skills/docs/SKILL.md @@ -116,6 +116,44 @@ description: Вести содержимое документов канона дать этому остаться в контексте. Признак: ты правил разбор, опираясь на то, чего нет ни в одном документе. +## Обращение к соседним плагинам + +Два раздела ниже — запись в `review.md` и промоут в конвенции — берут форму у +конвейера ревью: она принадлежит ему, а не канону. Берут **вызовом скилла**, а не +чтением файла по пути. + +**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов. +Правится дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Чем оборачивается отсутствие конвейера — в каждом из двух разделов отдельно: без +него работа не отменяется, отменяется только его процедура. + ## Запись в `review.md` Файл держит два раздела с разными сроками жизни — журнал дефектов и настройку diff --git a/av-dev-docs/skills/init/SKILL.md b/av-dev-docs/skills/init/SKILL.md index 357c641..c68a7c2 100644 --- a/av-dev-docs/skills/init/SKILL.md +++ b/av-dev-docs/skills/init/SKILL.md @@ -64,6 +64,43 @@ description: "Завести новый проект — сессия вопро - **Развилка замысла — человеку, механика — сама.** Имена файлов, слаги, порядок строк не выноси. +## Обращение к соседним плагинам + +Два шага из девяти — вызовы чужого: OpenSpec заводит конвейер, каталог задач +ведёт плагин задач. Ни того, ни другого `init` не делает руками. + +**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов. +Правится дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Чем оборачивается отсутствие каждого — на самих шагах 3 и 7. Заведение проекта +из-за этого не останавливается: проект без конвейера и без учёта задач законен. + ## Порядок работы 1. Прочитай бриф целиком. Выпиши, на какие блоки интервью ответ уже есть. @@ -74,9 +111,8 @@ description: "Завести новый проект — сессия вопро ни сверка требований. Каталог принадлежит конвейеру, а не канону, поэтому здесь только вызов — ни команды, ни формы файла `init` не знает. - **Вызов не разрешился — плагина конвейера в проекте нет.** Это законный исход, - а не поломка: проект без конвейера живёт без OpenSpec. Скажи это строкой в - докладе и иди дальше; `docs.py check` о каталоге тоже промолчит. + **Вызов не разрешился** — проект без конвейера живёт без OpenSpec законно: + строка доклада, и дальше; `docs.py check` о каталоге тоже промолчит. 4. Заведи `docs/.pm.json` с текущей версией канона. 5. Напиши заполняемые документы. **Бриф переезжает в `passport.md`** и отдельным файлом не остаётся: два дома для одного замысла разойдутся на diff --git a/av-dev-pipeline/skills/openspec/SKILL.md b/av-dev-pipeline/skills/openspec/SKILL.md index c65a300..085d76a 100644 --- a/av-dev-pipeline/skills/openspec/SKILL.md +++ b/av-dev-pipeline/skills/openspec/SKILL.md @@ -113,9 +113,37 @@ python3 $os form # слепок формы против жив или `config.yaml` остался примером; - человек — когда конвейер отказался работать без источника требований. -Вызов идёт **через пространство имён**, а не путём в дерево плагина. Не -разрешился — плагина конвейера в проекте нет, и тогда OpenSpec заводит человек -командой выше; скажи это строкой, а путь не выдумывай. +**Копия.** Дом правила — `shared/plugin-boundary.md` в репозитории плагинов. +Правится дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Здесь это значит: вызов не разрешился — плагина конвейера в проекте нет, и тогда +OpenSpec заводит человек командой выше. ## Чего этот скилл не делает diff --git a/av-dev-pipeline/skills/review-pipeline/SKILL.md b/av-dev-pipeline/skills/review-pipeline/SKILL.md index 45c5320..6fa2645 100644 --- a/av-dev-pipeline/skills/review-pipeline/SKILL.md +++ b/av-dev-pipeline/skills/review-pipeline/SKILL.md @@ -60,10 +60,42 @@ description: "Конвейер ревью изменения, устроенны проекте уже лежат свои `.claude/skills/review-pipeline`, `.claude/skills/task-pipeline`, `.claude/skills/task-batch` или `.claude/agents/<проект>-review-*.md` — снеси их. Иначе короткое имя разрешится - в устаревшую проектную копию, молча и без признаков подмены. По той же причине - **скиллы этого плагина зовутся с пространством имён**: - `av-dev-pipeline:review-pipeline`, `av-dev-pipeline:task-pipeline`, - `av-dev-pipeline:task-batch`. + в устаревшую проектную копию, молча и без признаков подмены. + +### Обращение к соседним плагинам + +**Копия.** Дом — `shared/plugin-boundary.md` в репозитории плагинов. Правится +дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Своих скиллов это касается ровно так же: `av-dev-pipeline:review-pipeline`, +`av-dev-pipeline:task-pipeline`, `av-dev-pipeline:task-batch` — подменяется +короткое имя, а не чужое. ## Темы, источники и процессные документы diff --git a/av-dev-pipeline/skills/task-batch/SKILL.md b/av-dev-pipeline/skills/task-batch/SKILL.md index fbc11e0..b035f55 100644 --- a/av-dev-pipeline/skills/task-batch/SKILL.md +++ b/av-dev-pipeline/skills/task-batch/SKILL.md @@ -27,12 +27,43 @@ description: Проводит несколько задач разом — пл - **OpenSpec и скиллы `opsx:*`** — на них стоит цикл внутри каждого сабагента и проход `review-specs` финальной сверки. Проекта без OpenSpec это касается так же, как одиночного пайплайна (см. его раздел «Предпосылки»). -- **Скиллы зовутся с пространством имён**: `av-dev-pipeline:task-pipeline`, - `av-dev-pipeline:review-pipeline`, `av-dev-tasks:tasks`. Короткое имя - может разрешиться в устаревшую проектную копию, и это произойдёт молча — в - charter'е сабагента пиши полное имя, он твоего контекста не видит. - **Проектные копии этих скиллов и агентов при установке плагина удаляются.** +### Обращение к соседним плагинам + +**Копия.** Дом — `shared/plugin-boundary.md` в репозитории плагинов. Правится +дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +**У батча правило строже одним пунктом: полное имя обязательно и в charter'е +сабагента.** Сабагент твоего контекста не видит, короткое имя разрешает у себя, и +подмена на устаревшую проектную копию случится там, куда ты уже не смотришь. + Перед стартом прочитай `CLAUDE.md` проекта: оттуда берутся **имя основной ветки** (оно подставляется в каждую команду git ниже), команда и семантика гейта, инварианты и что запускать запрещено. Раскладка нумерованных артефактов — diff --git a/av-dev-pipeline/skills/task-pipeline/SKILL.md b/av-dev-pipeline/skills/task-pipeline/SKILL.md index dc4907f..99498df 100644 --- a/av-dev-pipeline/skills/task-pipeline/SKILL.md +++ b/av-dev-pipeline/skills/task-pipeline/SKILL.md @@ -22,9 +22,6 @@ description: "Автономно проводит одну задачу чере **Проект без OpenSpec этим пайплайном не ведётся** — подключай OpenSpec, а не вырождай цикл: ветка деградации здесь не пишется, потому что непроверенная ветка деградации хуже честного отказа. -- **Скиллы зовутся с пространством имён** — `av-dev-pipeline:review-pipeline`, - `av-dev-docs:docs`, `av-dev-tasks:tasks`. Короткое имя может разрешиться в - устаревшую проектную копию, и это произойдёт молча. - **Проектные копии этих скиллов и агентов удаляются при установке плагина** (`.claude/skills/` — и голые имена `task-pipeline`, `review-pipeline`, `task-batch`, и с префиксом проекта: `<проект>-task-pipeline`, @@ -32,6 +29,42 @@ description: "Автономно проводит одну задачу чере `.claude/agents/<проект>-review-*.md`). Две копии одного скилла расходятся, и побеждает та, что короче названа. +### Обращение к соседним плагинам + +**Копия.** Дом — `shared/plugin-boundary.md` в репозитории плагинов: правило +общее для всех семи скиллов, зовущих чужое, и ни один плагин им не владеет. +Правится дом, а не этот файл. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + + + +Пайплайн зовёт `av-dev-pipeline:review-pipeline`, `av-dev-docs:docs` и +`av-dev-tasks:tasks`. Чем оборачивается отсутствие каждого — на самих шагах и в +разделе «Границы». + Перед стартом прочитай `CLAUDE.md` проекта и то, на что он ссылается, если ещё не в контексте. Проектные факты, нужные ревью — инварианты, семантика гейта, объёмы, модель угроз, прецеденты, — живут в **документах канона** `av-dev-docs`; diff --git a/shared/plugin-boundary.md b/shared/plugin-boundary.md new file mode 100644 index 0000000..5f4fd30 --- /dev/null +++ b/shared/plugin-boundary.md @@ -0,0 +1,55 @@ +# Граница между плагинами + +**Это дом.** Правило обращения к соседнему плагину нужно всем, кто зовёт чужой +скилл, — а таких скиллов семь в трёх плагинах, и ни один из трёх правилом не +владеет. Поэтому дом стоит снаружи, а плагины везут **копии**, помеченные +разметкой `copies.py`. + +Правится **здесь**. Копия, поправленная у себя, — расхождение, а не правка. + +Дом заведён по замеру, а не на всякий случай. К моменту раскола правило стояло в +пяти местах в пяти редакциях: + +| Где стояло | Довод | Ветка «не разрешился» | +| --- | --- | --- | +| `task-pipeline` | устаревшая проектная копия | нет | +| `task-batch` | то же | нет | +| `review-pipeline` | вшито в пункт про удаление проектных копий | нет | +| `openspec` | путём в чужое дерево — никогда | есть | +| `canon` | — | есть | + +Два разных довода, и ни в одном месте не было обоих. Три места из пяти молчали о +том, что делать, когда вызов не разрешился, — то есть о единственном, ради чего +правило и написано. + +**Что в дом не идёт: чем оборачивается отсутствие конкретного соседа.** «Нет +`av-dev-tasks` — учёт остаётся владельцу» знает только конвейер; «нет конвейера — +`docs.py` о каталоге `openspec/` молчит» знает только канон. Правило общее, +последствие местное, и держать последствия здесь значило бы завести дом, который +знает про всех своих потребителей. + + + +Плагины `av-dev` ставятся порознь, и ни один не вправе считать, что сосед на +месте. + +**Чужой скилл зовётся полным именем** — `av-dev-docs:canon`, +`av-dev-tasks:tasks`, `av-dev-pipeline:review-pipeline`. Короткое имя может +разрешиться в устаревшую проектную копию из `.claude/skills/`, и подмены не будет +видно ни в докладе, ни в поведении. + +**Путь в дерево чужого плагина не пишется никогда.** `$CLAUDE_PLUGIN_ROOT` ведёт +только в свой плагин; вычисленный от него путь к соседу либо не откроется, либо +откроет чужую установку. Нужен чужой справочник — зови владеющий им скилл, он +прочитает его сам. + +**Вызов не разрешился — плагина в проекте нет.** Это исход, а не поломка: назови +строкой доклада, чего теперь не делает никто, и продолжай работу. Молчать нельзя, +пропуск неотличим от сделанного; выдумывать обходной путь нельзя тоже. + +**Присутствие узнаётся вызовом или следом в проекте, но не объявлением.** Перечня +установленных плагинов проект не ведёт — он разошёлся бы с действительностью +молча. Что сосед здесь работал, видно по заведённому им файлу: `docs/.pm.json` — +канон, `<каталог задач>/.tasks.json` — задачи, `openspec/config.yaml` — конвейер. + +