@rt-tools/agent-kit
v0.24.0
Published
Переносимый слой правил для агента: законы, хуки, проверки и агенты, раскладываемые в репозиторий одной командой
Maintainers
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 не пишет. Файл принадлежит дереву, в нём лежит и то, о чём пакет не знает вовсе, и молчаливое слияние теряло бы несовпавшее.
Генератора черновиков правил по закону.
