Files
dev-skills/decisions/54-plugin-seam-rule-home.md
T
av bf6a173115 журнал решений: разложен по теме на файл, метки решений стали номерами
- DECISIONS.md (4040 строк, 65 тем) → decisions/, файл на тему плюс указатель;
- буквенные метки решений заменены сквозными Р1–Р234, следствия получили
  префикс С при прежних номерах: схема букв выродилась до пятибуквенных и
  сломалась — `АЕАКЛ` была занята и темой 53, и темой 65;
- 42 перекрёстные ссылки переписаны под новые номера и стали живыми; где номер
  означал тему, а слово стояло «решение», формулировка исправлена.
2026-08-13 12:40:56 +03:00

97 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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) — и видно не только, что порог верен, но и насколько он не
на грани.