- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель; - буквенные метки решений заменены сквозными Р1–Р234, следствия получили префикс С при прежних номерах: схема букв выродилась до пятибуквенных и сломалась — `АЕАКЛ` была занята и темой 53, и темой 65; - 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер означал тему, а слово стояло «решение», формулировка исправлена.
9.0 KiB
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) — и видно не только, что порог верен, но и насколько он не на грани.