npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rt-tools/agent-kit

v0.24.0

Published

Переносимый слой правил для агента: законы, хуки, проверки и агенты, раскладываемые в репозиторий одной командой

Readme

@rt-tools/agent-kit

Переносимый слой правил для агента: законы, шаблоны правил и паттернов раскладываются в репозиторий одной командой и обновляются следующей, не затирая того, что проект дописал сам.

Зачем

Правила, по которым агент правит код, копятся в каждом репозитории заново. Скопированные из соседнего они устаревают молча: правку в исходнике никто не переносит, а расхождение видно только по последствиям.

Пакет разделяет текст на три слоя. Закон — что должно быть верно; он не знает ни путей, ни имён файлов. Правило — каким приёмом это делается; приём переносится между репозиториями так же, как закон. Паттерн — готовый код приёма.

Все три везёт пакет. В проекте остаётся то, чего пакет знать не может: имена этого дерева. Они живут при каждом правиле отдельным файлом — implementation.md, — и пишет его проект.

Как пользоваться

pnpm add -D @rt-tools/agent-kit

npx agent-kit list      # что везёт пакет и что из этого взято здесь
npx agent-kit init      # спросить законы галочками и завести .claude/rt-kit.json
npx agent-kit sync      # разложить выбранное в docs/constitution/
npx agent-kit doctor    # что разложено, что отстало, чего не хватает
npx agent-kit adopt     # отдать пакету файлы, лежащие на его путях не от него
npx agent-kit stats     # чем пользовались, чем ни разу, обо что спотыкались
npx agent-kit cost      # сколько весит вход в работу, одно правило и весь слой

init называет и то, чего пакет ждёт от дерева: значения дырок, которые придётся вписать в vars. Узнавать о них отказом первой же раскладки — значит начинать установку с ошибки.

В гейте пуша:

npx agent-kit sync --check

Команда ничего не пишет и отказывает, если разложенное отстало от пакета, его правили руками, компаньон правила остался черновиком или разложенный гард не назван в настройке агента.

Раскладка отказывает и там, где раньше молчала:

  • у ресурса есть виды, но ни один не отвечает выбору дерева — правило легло бы без инструмента, который оно зовёт;
  • ресурсы правлены позже, чем собран пакет, из которого идёт раскладка, — легла бы прежняя редакция, а команда назвала бы это сделанным;
  • на пути пакета лежит файл не от него — его отдают пакету командой adopt, и прежнее содержимое остаётся рядом под именем с пометкой .before-rt-kit.

Что где лежит

| Род | Куда ложится | Что это | | --- | --- | --- | | laws | docs/constitution/ | что должно быть верно | | rules | .claude/skills/<имя>/SKILL.md | каким приёмом это делается | | patterns | .claude/skills/<имя>/SKILL.md | готовый код приёма | | skills | .claude/skills/<имя>/SKILL.md | скил, у которого нет закона над собой | | hooks | .claude/hooks/ | что не даёт нарушить | | defaults | .claude/rt-kit/defaults/ | карта гейта и профиль дерева — умолчаниями | | agents, commands, workflows | .claude/ | роли, слеш-команды и многошаговые прогоны | | checks | tools/ | проверки, которые зовёт гейт | | templates | .claude/rt-kit/templates/ | формы правила, паттерна, компаньона и надстроек | | samples | docs/ | образцы, которые копируют в рабочий файл: папка задачи, спек домена |

Правило, паттерн и скил ложатся одинаково — все три скилы; различает их kind во вступлении файла. Скил без закона стоит рядом с лестницей, а не в ней: он не про то, что должно быть верно в продукте, а про то, как здесь делается работа, — витрина, генератор, заведение самого скила. Выдумывать ему закон ради лестницы нельзя: закон с одним правилом и без единой статьи о продукте разъезжается с остальными при первой же правке.

Законы лежат в двух слоях. Общий — docs/constitution/<закон>.md, верный любому приложению этого класса. Закон приложения — docs/constitution/application/<закон>.md: деньги, локали, доступ, владеющая сущность, видимость в поиске. Без этих предметов его не существует, и предметность в нём законна. Слой в ссылке не отражается: law: в шапке правила называет закон одним словом, и переезд между слоями этих строк не переписывает.

Правило и его компаньон

Правило называет приёмы и раскладку, общие для деревьев мастерской: libs/<семья>/<домен>/<слой>, слои, семьи, роды файлов. Они одинаковы везде, и заставлять каждое дерево выписывать их заново значило бы заводить столько редакций одного текста, сколько репозиториев.

Чего правило не называет — конкретных путей, доменов и портов. Раздел «Где это лежит» в нём отсылает к компаньону, а порт стенда стоит дыркой со значением из конфига: путь, названный в правиле, врёт в первом же дереве, которое держит код иначе, и врёт молча.

Рядом, в implementation.md, живёт то, чего пакет знать не может: ключ задач, адрес борды, префикс компонентов, валюта хранения, имена доменов — и привязка каждой статьи правила к символу, который её исполняет.

Черновик приезжает не пустым: статьи правила переносятся в таблицу привязки заранее. Их текст — ключ связи, и переписанный руками он расходится с правилом молча; проекту остаётся вторая колонка, а не перепечатывание первой.

Черновик компаньона sync кладёт один раз, при первой раскладке правила, и больше к нему не возвращается: своего текста у пакета там нет, а перекладывать значило бы стирать написанное проектом. Пока в черновике осталась метка <!-- заполняет проект -->, sync --check отказывает: правило без имён этого дерева — это указание без адресата.

Компаньон — принадлежность правила, а не всякого скила. У скила без закона статей нет, привязывать нечего, и sync черновика ему не кладёт: здешнее он несёт прямо в тексте или в надстройке overrides/skills/<имя>.md. Отказ sync --check за незаполненный черновик его тоже не касается.

Виды одного ресурса

Есть приёмы, у которых один и тот же закон исполняется разными командами: заявка на слияние открывается gh, glab или az repos. Обезличить их до общего текста нельзя — правило, из которого убрали команду, перестаёт быть указанием.

Такой ресурс лежит в пакете в нескольких видах — git-workflow.github.md, git-workflow.gitlab.md, git-workflow.azure.md, — а проект выбирает вид один раз, при init. Разложен будет ровно один, под общим именем git-workflow: агенту, который его читает, знать хостинг незачем.

npx agent-kit init --host gitlab     # или спросит, если запуск из терминала

Выбор уезжает в variants конфига. Ось без ответа отбивает раскладку целиком: дерево, не назвавшее свой хостинг, осталось бы вовсе без правила поставки — и заметить это можно было бы только по тому, что гейт перестал его требовать.

Хуки

Закон и правило, которых никто не открывает, не действуют, поэтому пакет везёт и хуки, которые их зовут.

Гейт правил. skill-gate.sh отбивает правку, пока не загружено правило под неё, skill-loaded.sh записывает загрузку, skill-gate-rearm.sh взводит гейт заново после сжатия контекста, constitution-index.sh печатает указатель законов на старте сессии.

Сторожевые хуки. Главная ветка, поставка, документ в одном коммите с правкой, проверки перед пушем, линтер по следам правки, пишущие запросы к хранилищу, второй сервер разработки, якорь для спек, переизобретение готового, формат сообщения коммита, закреплённый профиль браузера.

Карта и профиль — умолчанием, а не пустой формой. Хук везёт механизм, а то, что он зовёт и называет, лежит рядом в двух файлах. Деревья мастерской устроены одинаково, поэтому умолчание везёт пакет:

| Файл | Кто пишет | Что в нём | | --- | --- | --- | | .claude/rt-kit/defaults/gate-map.sh | пакет | что правится — какое правило: тесты, компоненты, стили, барели, документы, команды поставки | | .claude/rt-kit/defaults/project.sh | пакет | запускатель по локфайлу, линтеры, форма имени ветки, образцы переизобретения | | .claude/rt-kit/gate-map.sh | проект, необязательно | род файлов, которого нет у других: витрина, свой генератор | | .claude/rt-kit/project.sh | проект, необязательно | порты стендов, свои проверки, свои пары «правка — документ» | | .claude/rt-kit/browser-device-id | проект | закреплённый профиль браузера этой машины |

Надстройка грузится второй и объявляет ту же функцию заново; чтобы дописать, а не заменить, она зовёт умолчание тем же именем с суффиксом _default. Нет надстройки — действует умолчание; нет ни того ни другого — хук пропускает: пустой гард лучше гарда, отбивающего наугад.

Карта хуков в настройке агента. Разложенный гард зовёт запись в .claude/settings.json — файле, который принадлежит дереву. Каждый гард несёт строку # rt-hook: <событие> <образец> и сам говорит, когда его звать; из этих строк sync собирает готовый раздел hooks и печатает его, а sync --check считает неподключённый гард расхождением. Пишет в настройку проект: гард, которого никто не зовёт, неотличим от гарда, который всё пропускает.

Карта гейта вправе назвать несколько правил, по одному в строке: доменное правило файла и те, что действуют вторым слоем. Гейт потребует первое незагруженное — и только то, чьё правило в дереве есть: имя, от которого дерево отказалось списком, он пропускает молча. Второй слой она выбирает и по тексту правки, а не только по имени файла: обращение к среде исполнения приходит в обычный сервис, а число-настройка — в обычный класс.

Выбор законов

Половина законов пакета про то, чего в конкретном приложении нет вовсе: у сервиса без админки нет ни её списков, ни её навигации. Поэтому init спрашивает, какие законы брать, а не кладёт все пятнадцать молча.

npx agent-kit init                       # спросить галочками
npx agent-kit init --all                 # взять все, ни о чём не спрашивая
npx agent-kit init --laws access,delivery,verifiability

Без терминала — в CI, в конвейере, в чужом скрипте — спрашивать некого, и init без флага отказывает вместо того, чтобы решить за проект: «взять всё» тоже решение, и принимать его молча он не вправе.

Выбор уезжает в конфиг ключом only и оттуда же правится потом: init заведённый конфиг не трогает. Имена законов — из agent-kit list, там же видно, что взято, что не выбрано и что пропущено.

Отказ от закона снимает его правила и паттерны сам. Связь читается из вступления ресурсов — у правила стоит law, у паттерна rule, — и перечислять потомков в skip не надо: строка, которая после этого ничего не снимает, называется вслух предупреждением, а раскладка идёт дальше. Каскад идёт только сверху вниз: отказ от паттерна ни правила, ни закона не трогает.

Правило, названное в only при невыбранном законе, тоже называется вслух: раскладка говорит, что оно не приедет и по какому родителю. Файл такого правила, разложенный прежней настройкой, перечисляется отдельно от брошенного — дерево от него не отказывалось.

Ресурс, ушедший из набора совсем, пакет помнит по имени: файл, положенный им в дерево прежней редакцией, назван при раскладке вместе с причиной снятия. Убирает его дерево — в чужие файлы пакет не пишет.

Конфиг

.claude/rt-kit.json коммитится: раскладка обязана повторяться на чужой машине без вопросов.

{
    "vars": { "mainBranch": "main" },
    "layout": { "laws": "docs/constitution" },
    "variants": { "host": "gitlab" },
    "only": ["laws/application/access.md", "laws/delivery.md"],
    "skip": ["laws/lists.md"]
}
  • vars — значения дырок {{имя}} в тексте пакета. Своих дырок пакет не ставит: пути он называет прямо, потому что деревья мастерской раскладываются одинаково. Дырка остаётся для надстроек проекта. Неподставленная — отказ раскладки, а не строка в разложенном тексте: {{mainBranch}} посреди правила агент прочтёт как имя.
  • variants — выбор по осям различия, объявленным пакетом в assets/variants.json. Ось без ответа отбивает раскладку.
  • layout — куда класть каждый род ресурса. Умолчания менять без нужды не стоит: правила ссылаются на законы теми же путями.
  • only — что проект выбрал, идентификаторами вида laws/<закон>.md, у закона приложения — laws/application/<закон>.md. Пусто — берётся всё. Ограничивает только те роды, которые сам называет: перечислив законы, проект говорит о законах, а не обо всём, что пакет везёт, — шаблоны при нём остаются.
  • skip — ресурсы, от которых проект отказался, теми же идентификаторами. Вычитает из выбранного, поэтому отказ от одного закона не требует переписывать весь список. Правила при отвергнутом законе и паттерны при них перечислять не надо: их снимает каскад.
  • rolesOff — роли, вызов которых дерево перестало считать обязательным, именами файлов ролей без расширения. Гард при такой роли выходит молча, а сама роль остаётся разложенной и зовётся руками. От skip отличается тем, что ничего не убирает: отказ от файла роли снял бы её вместе с возможностью позвать, а гард при ней остался бы лежать и отбивать. Настройка, которую не прочитать, выключением не считается — гард судит, как судил.

Надстройки

Проект дописывает своё не в разложенный файл, а рядом — в .claude/rt-kit/overrides/<идентификатор ресурса>. Правка разложенного файла теряется на следующем sync, и пакет на неё отказывает, вместо того чтобы переписать молча.

Слияние идёт по разделам ## :

| В надстройке | Что происходит | | --- | --- | | заголовок, который есть у пакета | раздел замещается целиком | | заголовок, которого у пакета нет | раздел дописывается в конец | | заголовок без тела | раздел пакета снимается |

Так правка пакета доезжает во все разделы, которых проект не трогал, а проектная история решений остаётся при проекте.

Что разложено

Каждый разложенный файл несёт шапку с версией пакета и суммой тела. По ней sync отличает три случая: файл отстал от пакета, файл правили руками, файл положен вообще не пакетом. Первый перекладывается, на двух других раскладка отказывает и называет их поимённо.

Отказ хотя бы по одному файлу не пишет ничего: половина разложенного хуже целого.

Наблюдения и сводка

Правило, которого никто не открывает, не действует, — и узнать об этом было нечем. Гарды пишут наблюдения: правило загружено, гейт отбил правку, гард отказал. Строка несёт имя ресурса пакета, род события, род правки, версию и признак сессии; путей дерева, имён его доменов и имени его самого в ней нет — значение со слэшем не пишется вовсе.

npx agent-kit stats --days 3     # за отрезок; без довода — за три дня
npx agent-kit stats --json       # то же машиночитаемо

Самая ценная строка сводки — не «чем пользовались», а что разложено и не загружено ни разу: чем пользуются, видно и по работе, а мёртвый ресурс ничем себя не выдаёт.

Цена контекста

Сводка говорит, чем пользовались; цена — сколько это стоило. Заход платит за слой правил окном, и до этой команды вес того, что он получает целиком, не считало ничто.

npx agent-kit cost                  # вход в работу, самое тяжёлое правило, весь слой
npx agent-kit cost --rule <имя>     # взвесить названное правило
npx agent-kit cost --json           # то же машиночитаемо — этим числа кладут в замысел

Считается не файл, а то, что заход получает: описание правила приходит ему полем, словарь и карта хода — выводом хуков. Меряется в символах и байтах — тем, что берётся на месте, без сети. Число сравнимо только с числом, снятым той же командой; чем считано, стоит в первой строке вывода.

Наблюдения лежат в .claude/rt-kit/observations/ файлом на день и снимаются через тридцать дней. Запись выключается ключом "observe": false в конфиге — целиком, а не частями. Каталог просится в список игнорируемого; вписывает его проект — в чужие файлы дерева пакет не пишет.

Предложения обратно в пакет

Разбор закрытой задачи и раньше ставил каждому предложению адрес — «пакет», «компаньон» или «дерево», — но результат оставался в переписке, и правки переносили руками. Теперь предложения ложатся файлом в .claude/rt-kit/proposals/, блоком на предложение:

## пакет · rules/styling-bem.md

- **место:** раздел «Ловушки», в конец
- **повод:** что в этой задаче пошло не так без этого правила

> Готовый текст правки.
npx agent-kit propose --dry-run   # что уехало бы
npx agent-kit propose             # отправить груз в приём

Чтобы грузу было чем представиться, у дерева должен быть токен. Путей завести его два, и человек выбирает доводом:

npx agent-kit enroll --code <код приглашения>   # обменять приглашение на токен
npx agent-kit enroll --token <токен>            # положить токен, выданный в админке приёма

Обмен по коду. Код одноразовый и годен ограниченное время; имя дерева называет приглашение, а не обращение. Адрес приёма без TLS команда отбивает у себя, не доходя до сети: токен уходит единственным ответом на обращение.

Выданный токен. Владелец приёма выдаёт токен прямо в админке и передаёт его человеку; обменивать не на что, и в сеть команда не идёт вовсе — ни адрес приёма, ни TLS этому пути не нужны.

Два довода вместе не идут, и ни одного — тоже: отказ называет оба пути. Токен ложится одинаково, каким бы путём ни пришёл: файл, названный ключом token, правами «читает только владелец файла». Лежащий токен команда молча не перезаписывает ни на одном из путей — для этого есть довод --force.

Груз уезжает при каждом прогоне тремя родами: сводка наблюдений со снимком надстроек, предложения с адресом «пакет» — когда они есть — и разборы происшествий. Прогон без замечаний тоже говорит, чем пользовались, чем не пользовались ни разу и что дерево переопределило. Отправленное предложение помечается в том же файле и второй раз не уезжает.

Уезжает груз в закрытый приём, а не в открытую очередь работ: сводка говорит о рабочих привычках команды — чем пользуются, обо что спотыкаются, сколько раз признавали промах. Адрес приёма объявлен настройкой дерева, а не зашит в код пакета.

Перед отправкой сводка и тексты предложений сверяются на адрес дерева — абсолютный путь, имя корня, адрес удалённого репозитория. Нашлось — отказ с номером строки, и отбивается вся отправка целиком: «уехало два из трёх» читается как «всё в порядке». Разбор происшествия проверкой не накрыт: он по устройству называет файлы дерева, где промах случился.

Что для этого нужно

Наблюдения и сводка живут целиком на машине; в сеть ходит только отправка, и только по команде человека. Приём — своя служба, а не чужая: она поднимается там, где решит владелец пакета.

| Где | Что нужно | | --- | --- | | у потребителя | jq — его требуют и сами гарды | | у потребителя | адрес приёма ключом intake в .claude/rt-kit.json — берётся у владельца приёма вместе с кодом приглашения | | у потребителя | токен дерева в файле вне дерева, названном ключом token | | у приёма | заведённое дерево: токен выдаёт его команда и печатает один раз |

Адреса приёма пакет не знает: приём поднимает владелец, и у каждой мастерской он свой. Спрашивается он у того же человека, который выдаёт код приглашения, — код и адрес идут парой и порознь не работают. Вид адреса — https://<приём мастерской>; без TLS команда запрещает обмен у себя, не доходя до сети: токен приходит единственным ответом, и по открытому пути его прочитает любой. Исключение сделано только для локальной машины.

Признак, которым дерево представляется приёму, считается хешем от адреса его удалённого репозитория: адрес по нему не восстанавливается, а у двух рабочих копий одного репозитория он один. Репозитория нет — признак называется ключом tree.

Адреса нет, токена нет, токен отозван — отправка отказывает ненулевым кодом и называет, чего именно не хватило и где это объявляется. Молчаливая отправка выглядела бы работающей.

Роли и конвейеры

Пакет везёт шесть ролей субагентов и два конвейера из них.

| Роль | Что делает | | --- | --- | | business-analyst | что работа даёт владельцу, что выкидывается без потери цели | | project-manager | декомпозиция с границами и признаками готовности, приёмка по исходному запросу | | qa-engineer | тесты, сборка, линтеры, замеры в браузере, состязательный разбор правки | | spec-writer | договорённость о продукте до кода — спек фичи по разбору просьбы | | spec-critic | что в договорённости недосказано и где два прочтения | | skill-curator | разбор закрытой задачи: что из правил помогло, чего не хватило |

Конвейер plan ведёт от разбора просьбы владельца до замысла — нужность, договорённость, критика, этапы. Конвейер feature — от плана до приёмки, с веером проверок посередине.

Роль вопросов владельцу не задаёт: ни она, ни конвейер до него не достучатся. Поэтому разбор ведёт главный агент, а роли стоят по обе стороны от него — разведка до, конвейер после.

skill-curator приезжает и слеш-командой — о ней и остальных двух ниже.

Слеш-команды

Род commands ложится в .claude/commands/, по файлу на команду. Имя команды — это имя файла: next-session.md зовётся /next-session. Больше нигде команды не объявляются — перечня, который пришлось бы держать в согласии с каталогом, нет вовсе. Строка description: во вступлении файла — то единственное, что агент видит до вызова и по чему решает, брать ли команду; argument-hint: говорит, что она принимает.

| Команда | Ресурс | Что делает | | ------------------- | ------------------------------ | -------------------------------------------------------------- | | /next-session | commands/next-session.md | закрывает заход: главная ветка, влитые ветки, передача | | /skill-curator | commands/skill-curator.md | разбирает закрытую задачу и выгружает предложения файлом | | /agent-kit-digest | commands/agent-kit-digest.md | сводит накопленные предложения и наблюдения в правки ресурсов |

/next-session приводит дерево к главной ветке — переходом на неё, если работа шла по правилу и PR влит, и вливанием в текущую ветку во всех прочих случаях, — снимает влитые локальные ветки, называет невлитые и пишет передачу для следующего захода. Незакоммиченная правка останавливает её до первого действия; поставки она не касается.

/skill-curator — та же роль, приехавшая командой: она собирает сводку о задаче и список загруженных за неё правил, без которых разбор выродится в пересказ, и кладёт предложения файлом с адресом в заголовке.

/agent-kit-digest зовётся в репозитории самого пакета, а не в дереве, где он стоит: там лежат ресурсы, которые предстоит править, и видно всех потребителей сразу.

Разложенная команда правится как любой разложенный файл — не на месте: либо ресурс в пакете, либо надстройка .claude/rt-kit/overrides/commands/<имя>.md. Свою команду дерево заводит файлом рядом; файл без шапки раскладки пакет чужим считает и не перезаписывает.

Слешем зовётся не только команда: скилы — правила, паттерны и скилы без закона из .claude/skills/ — и конвейеры из .claude/workflows/. Что из всего этого разложено и откуда взялось, говорят npx agent-kit list и npx agent-kit doctor.

Как этим пользуются в дереве

Всё, что выше, пакет объясняет человеку. Агенту то же самое объясняет скил agent-kit — ресурс skills/agent-kit.md: когда его брать, где что настраивается, в каком порядке идёт правка и как ставить пакет туда, где хуки и проверки уже свои.

Скил обезличен, как и остальные тексты пакета. Своё дерево дописывает к нему раздел про свои надстройки — надстройкой же, .claude/rt-kit/overrides/skills/agent-kit.md. Это и есть образец того, как механизм применяется к самому себе.

Проверки

Род checks ложится в tools/: сверка спеков с тестами, повторы, слои либ, пути в документах, переизобретение готового, классы без правила, расхождение схемы с миграциями, очередь работ и заведение задачи. Их же зовёт гейт пуша и на них ссылаются правила.

Пути и идентификаторы, которыми проверки живут, в код не зашиты: они читаются из .claude/rt-kit/checks.json через tools/rt-kit-checks.config.mjs. Незаполненный ключ означает умолчание, а не отказ, — проверка, которой в дереве нечего сверять, молчит.

Проверки, чей ход зависит от хостинга, лежат видами: board, check-board и task-new приезжают в дерево под общими именами, а разговаривают с тем хостингом, который проект выбрал при init.

Раскладка и право на запуск

Гарда зовут по пути, а не через оболочку, поэтому право на запуск — часть ресурса, а не случайность файловой системы. Раскладка снимает признак с файла в пакете и переносит на разложенный.

Без этого гард отвечает отказом доступа, то есть ненулевым кодом, а ненулевой код у гарда значит «правка отбита»: набор отбивает подряд всё, включая сборку и тесты, и причина при этом нигде не называется.

Чем проверяется сам пакет

Механизм раскладки покрыт спеками на TypeScript. Гарды, проверки и умолчания — файлы, которые пакет только перекладывает: линтер в assets/ не ходит, а спеки механизма исполняют TypeScript, а не то, что он перекладывает. Поэтому у исполняемых ресурсов свои наборы сценариев — tests/ в проекте пакета, на том же языке, что и сами ресурсы:

| Набор | Что проверяет | | --- | --- | | разбор ресурсов | каждый гард читается оболочкой, каждая проверка — разборщиком, право на запуск на месте | | гейт правил | выбор правила по роду файла и по тексту правки, вложенные вызовы, однократность за сессию, отказ в пользу работы | | гарды поставки | коммит в главную ветку, форма имени ветки, совпадение номеров задачи и заявки | | гард замысла | признак кода приложения, обход причиной, договорённость на диске | | гард документов | пара «правка и её документ», спутник правила, обход причиной | | умолчания | профиль дерева и карта гейта поштучно, вызов умолчания из надстройки | | проверки | слияние настроек по вложенным ключам, корни из настройки, а не из кода | | тексты | ни доменов конкретного дерева, ни портов числом, ни путей в правилах |

Гоняются они прогоном пакета: nx test зовёт tests/run.sh обёрткой. Сценарии не знают ни карты, ни доменов, ни портов конкретного дерева — всё, что им нужно, поднимается фикстурой.

Чего в пакете пока нет

Инструментов заведения задачи и сверки очереди под хостинги, кроме первого: правило поставки едет тремя видами, а команды при нём — одним. Раскладка об этом больше не молчит — она отказывает и называет оба выхода, — но самих инструментов под второй и третий хостинг нет.

Слияния карты хуков в настройку агента: пакет собирает готовый кусок и проверяет, что он вставлен, но в чужой JSON не пишет. Файл принадлежит дереву, в нём лежит и то, о чём пакет не знает вовсе, и молчаливое слияние теряло бы несовпавшее.

Генератора черновиков правил по закону.