- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель; - буквенные метки решений заменены сквозными Р1–Р234, следствия получили префикс С при прежних номерах: схема букв выродилась до пятибуквенных и сломалась — `АЕАКЛ` была занята и темой 53, и темой 65; - 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер означал тему, а слово стояло «решение», формулировка исправлена.
97 lines
9.0 KiB
Markdown
97 lines
9.0 KiB
Markdown
# 54. Стык плагинов: правило получило дом, адреса остались у владельцев (2026-08-09)
|
||
|
||
**Р202. Вопрос пришёл с другой стороны: ревью опирается на документы проекта, но
|
||
не должно жёстко предполагать, где файл лежит; напрашивалось оглавление адресов
|
||
и сводка возможностей скиллов в `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/` заводится **только для
|
||
фактов без владельца**; чужое с владельцем остаётся дома, а сходимость упоминаний
|
||
в чужих деревьях проверяет машина — `scripts/addresses.py`, тем же заходом.
|
||
|
||
**Что выяснилось при написании чекера: судить незнакомое нельзя.** Первый прогон
|
||
дал шесть находок, и три из них были не дрейфом, а свойством канона: `docs/**` —
|
||
шаблон, а `docs/accessibility.md` в двух местах — пример **своей темы проекта**,
|
||
которую канон разрешает заводить произвольно. Список тем открытый, значит
|
||
незнакомое имя опровергнуть нечем, и проверка «есть ли такой документ у
|
||
владельца» ловила бы законное. Переименование при этом ловится точно и по другому
|
||
основанию: канон, убирая слот, кладёт его в карту переездов `RETIRED` — она и
|
||
есть перечень запрещённого. Рядом одна догадка: имя, почти совпавшее с
|
||
каноническим, читается как опечатка. Порог замерен по репозиторию — законные
|
||
имена дают до 0.64, опечатки от 0.91, и между ними пусто.
|
||
|
||
Четвёртая находка оказалась настоящей: `REMAINING.md` иллюстрировал смысловой
|
||
дубль адресом `docs/specs/recognition.md` — слотом, упразднённым в версии 1
|
||
канона, то есть при десяти нынешних.
|
||
Пример, который сам протух, — ровно то, ради чего чекер и писался.
|
||
|
||
## Что из этого следует
|
||
|
||
**С179. Механизм честной деградации превращает протухший адрес в правдоподобный
|
||
доклад.** Там, где отсутствие источника — законный исход с названной ценой,
|
||
ошибка адреса неотличима от этого исхода. Значит адрес в таком месте обязан
|
||
сверяться машиной, а не аккуратностью: единственная альтернатива — ломаться
|
||
громко, а именно её деградация и убирает.
|
||
|
||
**С180. `shared/` — для фактов без владельца, и только.** У адресов владелец
|
||
есть, и вынести их наружу значило бы отобрать у него его же предмет. Признак
|
||
верного дома не «нужно нескольким», а «никому из них не принадлежит».
|
||
|
||
**С181. Общее правило и его последствия живут порознь.** Правило можно вынести в
|
||
дом, последствие — нет: оно знает про место, а место про правило знать не
|
||
обязано. Дом, вобравший последствия, становится реестром потребителей и
|
||
устаревает быстрее их всех.
|
||
|
||
**С182. Проверять надо запрещённое, а не незнакомое, когда словарь открыт.**
|
||
Открытый список делает «нет такого имени» неопровержимым, и проверка на
|
||
принадлежность перечню начинает ловить законное. Ловится ровно то, что владелец
|
||
объявил упразднённым: карта переездов — не побочный артефакт миграции, а
|
||
перечень запрещённого, и стоит она ровно там, где нужна.
|
||
|
||
**С183. Замер порога записывается рядом с порогом.** Число, выбранное на глаз,
|
||
через месяц неотличимо от подогнанного под один случай. Обе стороны разрыва
|
||
названы (0.64 и 0.91) — и видно не только, что порог верен, но и насколько он не
|
||
на грани.
|