Стандарт навыка

11 правил, каждое из провала на стенде

Правила, по которым навык заводят и принимают. Первые два решают, будет ли им вообще кто-то пользоваться, — остальное поправимо. Каждое правило с пометкой «прогон» стоило одного провала на стенде (см. METHOD.md).

Термины: автор — тот, чей модуль или библиотеку описывает навык (acme, shef, ваш вендор); префикс — короткое имя автора в имени навыка; справочный навык отвечает «как это устроено», операционный — «сделай по канону».

1. Имя — глагол или тема; каталог и name совпадают. Только [a-z0-9-], префикс автора первым: acme-new-import, acme-options-traits. Справочные — <префикс>-<библиотека>-<о чём>; операционные — <префикс>-new-<что>, <префикс>-use-<что> и другие (<префикс>-feedback). Операционным считается всё, что не справочное, и у него обязательны evals. Префикс нужен не для красоты: в одном проекте живут навыки нескольких авторов, и без префикса они перепишут друг друга при установке.

2. description пишется под задачу, а не под содержание. Это единственное, по чему навык выбирают: модель видит список имён и описаний и берёт один. Описание-оглавление («в навыке есть Modules, Events, PrepareFields») проигрывает описанию-поводу («нужно разобрать цену из строки вида 1 234,50 — брать этот»).

Что обязано быть в описании:

  • фразы задачи, а не названия классов: «вывести на странице список», «вынеси ключ в настройки модуля»;
  • граница: чего навык НЕ делает и какой брать вместо него. Именно границы разводят соседние навыки — без них модель берёт первый похожий. Соседи есть у каждого: агент — импорт, ajax-действие — API-клиент, трейты — модели;
  • длина от 80 до 1024 символов одной строкой. Верх — жёсткий лимит спецификации Agent Skills, длиннее обрезается молча; мерить mb_strlen, не wc -m в C-локали;
  • без привязки к вендору. Навык — для любого модуля на базе вашей библиотеки, а не только для ваших модулей. Прогон 1: «модуль линейки <вендор>.*» в описании — и ИИ-агент не брал навык для модуля acme.demo в пяти случаях из девяти; после правки — 9 из 9.

3. Тело — то, чего агент не знает и не выведет сам. Порядок действий, ловушки, «чего не делать». Пересказывать документацию ядра Битрикса не нужно: она у модели есть; а вот что prefilters замещает умолчания — нет.

4. Имена классов сверяются с кодом. Любой \Vendor\… в обратных кавычках проверяет bxshef lint --code против исходников модуля: нет такого класса — красный CI. Защита от навыка, который уверенно рассказывает про переименованное.

5. Навык не отсылает к коду, который агент может не увидеть. Сигнатура метода, namespace класса, имя файла — дословно в навыке. «Возьмите из модуля» — с точным путём и только как дополнение. Прогон 2: три угадывания из трёх там, где навык отсылал вместо того, чтобы сказать (глобальный класс без namespace, метод с массивом вместо строки, наследование без подключения модуля).

6. Модуль подключается до объявления класса. Файл, в котором класс делает extends, implements или use чего-либо из чужого модуля, начинается с \Bitrix\Main\Loader::includeModule('<модуль>') до слова class. PHP разбирает наследование при чтении файла; includeModule в теле метода к этому моменту не выполнялся. Навык, который показывает такой класс, показывает и эту строку. Прогон 3: Trait "…" not found там, где навык молчал.

7. Ссылки наружу — абсолютные, на GitHub. Навык ставится в чужой проект, относительный путь там ведёт в никуда.

8. Операционному навыку — evals/selection.json. Минимум три фразы: на себя, на соседа, <none>. Формат — {"input": "<фраза>", "expected": "<навык>" | ["<навык>", …] | "<none>", "notes": "…"}. Массив — когда верны несколько навыков. Одна и та же фраза в двух навыках не должна ждать разных ответов (lint это ловит). Реальные фразы с прогонов — с вводной строкой, как их ставит человек, с пометкой в notes. Фразу пишите как задачу, а не как механизм: «нужно по ночам пересчитывать остатки» проверяет описание, «сделай агента» — совпадение по слову.

9. Операционный навык заканчивается разделом «В конце» со ссылкой на <префикс>-feedback — навык отзыва, который есть в каждом наборе (заготовка в template/). Шаг, не вписанный в сам навык, до конца задачи не доживает — за первый прогон отзыв не был написан ни разу; после переноса шага внутрь навыка — 5 из 5.

10. После правки — bxshef lint и bxshef eval. Правка description без прогона evals — не правка: описание меняют ради выбора, а проверить выбор можно только прогоном. CI сделает это на PR, локально быстрее:

npx bxshef lint --dir skills --code <путь к исходникам модуля>
BXSHEF_EVAL_KEY=… npx bxshef eval --dir skills --repeat 3   # ключ — из окружения

11. Навыки автора живут в одном репозитории, не в репозитории модуля. ИИ-агент ставит и выбирает их как один набор. Связь с кодом держит CI в обе стороны: репозиторий навыков гоняет lint --code против свежих main модулей; репозиторий модуля забирает навыки и гоняет lint --code против себя — переименовали класс, PR модуля красный, пока не поправлен навык.

Репозиторий модуля (#9):

  1. Навыков в модуле нет — ни .claude/skills/, ни копий, ни синхронизации: две копии расходятся с первой же правки.
  2. README.md, раздел «Для ИИ-агентов» сразу после «Установки»: «Навыки для ИИ-агентов (Claude Code, Codex, Cursor) — в <owner>/<repo>. В проект: npx skills add <owner>/<repo>».
  3. CLAUDE.md / AGENTS.md — для агента, который правит сам модуль: навыки лежат там-то; правка класса или сигнатуры здесь требует правки навыка там; порядок — сначала PR в навыки, потом сюда.
  4. composer.json → "suggest": {"<vendor>/skills": "Навыки для ИИ-агентов: npx skills add <owner>/<repo>"} — пакета нет, это подсказка при composer require.
  5. CI модуля — «навыки не расходятся с кодом»: в общий каталог забрать репозиторий навыков, этот модуль из PR и соседние модули со свежего main (без соседей их классы с общим корнем, Vendor\…, будут «не найдены»), и bx-shef/skills-standard/action@v1 с dir: .check/skills/skills, code: .check/modules. eval-key не передаётся — eval пропускается: в модуле проверяется только связь классов с кодом. Готовый файл — template/module/skills.yml; .check/ — в .gitignore.

На проекте — по npx skills@latest:

  • npx skills add <owner>/<repo> ставит навыки в .agents/skills/<имя>/, для Claude Code делает ссылку в .claude/skills/ и пишет skills-lock.json (источник и хеш). Lock-файл коммитят; восстановить навыки по нему — npx skills experimental_install, обновить — npx skills update.
  • Файлы навыков в проекте не правят: замечание уходит отзывом (<префикс>-feedback), и навык правит автор.
  • Отзыву ничего настраивать не нужно: адрес приёмника записан в самом навыке отзыва, агент шлёт тикет curl-ом (feedback/README.md).

12. Раскладка репозитория навыков — skills/<имя>/SKILL.md. Рядом с навыком — его evals/, в корне — README.md и CI. Не из прогона — решение владельца (#10): шаблон лежал в .agents/skills/, эталон — в skills/, и автор, сверявший одно с другим, не знал, какому верить. .agents/ — каталог проекта, куда навыки ставят; в репозитории навыков ставить некуда. Пользователю раскладка не видна: npx skills add находит навыки в skills/ и кладёт их в проект в .agents/skills/; bxshef без --dir находит skills/ сам.

Источник: skills-standard/STANDARD.md — правки туда, сайт пересобирается сам.
CtrlI