@rt-tools/agent-kit 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/checks/board-paths.github.mjs +88 -0
- package/assets/checks/board-runs.github.mjs +8 -0
- package/assets/checks/board-titles.github.mjs +66 -0
- package/assets/checks/check-board.github.mjs +17 -4
- package/assets/checks/check-file-size.mjs +10 -2
- package/assets/checks/check-glossary.mjs +170 -0
- package/assets/checks/check-push-gate.mjs +59 -1
- package/assets/checks/check-schema-drift.mjs +12 -5
- package/assets/checks/spec-contract.mjs +9 -0
- package/assets/defaults/gate-map.sh +13 -4
- package/assets/defaults/project.sh +22 -3
- package/assets/docs/GLOSSARY.md +1 -1
- package/assets/hooks/browser-device-id.sh +20 -4
- package/assets/hooks/browser-guard-device-id.sh +5 -2
- package/assets/hooks/git-guard-delivery-folder.sh +19 -0
- package/assets/hooks/git-guard-delivery.sh +39 -0
- package/assets/hooks/git-guard-push-tests.sh +21 -1
- package/assets/hooks/grill-gate-ask.sh +25 -0
- package/assets/hooks/grill-gate.sh +12 -5
- package/assets/hooks/lint-after-edit.sh +44 -16
- package/assets/hooks/proposal-guard.sh +17 -1
- package/assets/hooks/skill-gate-layers.sh +7 -0
- package/assets/hooks/skill-gate.sh +29 -0
- package/assets/hooks/task-context-load.sh +10 -0
- package/assets/hooks/task-flow-context.sh +185 -0
- package/assets/hooks/task-flow-draft-guard.sh +92 -0
- package/assets/hooks/task-flow-guard.sh +27 -159
- package/assets/hooks/turn-exit-guard.sh +8 -1
- package/assets/hooks/window-fill-guard.sh +5 -1
- package/assets/laws/delivery.md +19 -0
- package/assets/laws/frontend-application.md +4 -0
- package/assets/laws/verifiability.md +21 -0
- package/assets/laws/work-conduct.md +15 -0
- package/assets/patterns/browser-verification-stand.md +7 -2
- package/assets/patterns/doc-style-write.md +41 -1
- package/assets/patterns/git-workflow-commit.github.md +15 -2
- package/assets/patterns/git-workflow-docker.md +14 -0
- package/assets/patterns/git-workflow-merge.md +18 -0
- package/assets/patterns/git-workflow-migration.md +11 -0
- package/assets/patterns/git-workflow-pr.github.md +6 -1
- package/assets/patterns/git-workflow-secrets.md +14 -0
- package/assets/patterns/git-workflow-stack.md +63 -1
- package/assets/patterns/spec-driven-domain.md +34 -1
- package/assets/patterns/spec-driven-rule.md +11 -0
- package/assets/patterns/spec-driven-sweep.md +57 -0
- package/assets/patterns/task-flow-archive.md +46 -14
- package/assets/patterns/task-flow-close.md +78 -2
- package/assets/patterns/task-flow-resume.md +17 -5
- package/assets/patterns/task-flow-start.md +42 -4
- package/assets/pitfalls/agent-kit.md +73 -3
- package/assets/pitfalls/doc-style.md +5 -0
- package/assets/pitfalls/git-workflow.github.md +68 -0
- package/assets/pitfalls/spec-driven.md +16 -0
- package/assets/pitfalls/task-flow.md +93 -0
- package/assets/pitfalls/turn-conduct.md +14 -0
- package/assets/rules/browser-verification.md +39 -0
- package/assets/rules/deploy-flow.azure.md +8 -0
- package/assets/rules/deploy-flow.github.md +18 -0
- package/assets/rules/deploy-flow.gitlab.md +8 -0
- package/assets/rules/doc-style.md +14 -0
- package/assets/rules/git-workflow.azure.md +5 -0
- package/assets/rules/git-workflow.github.md +85 -75
- package/assets/rules/git-workflow.gitlab.md +5 -0
- package/assets/rules/reuse-first.md +8 -0
- package/assets/rules/shared-code.md +5 -0
- package/assets/rules/spec-driven.md +14 -0
- package/assets/rules/task-flow.md +112 -112
- package/assets/rules/testing.md +14 -1
- package/assets/rules/turn-conduct.md +40 -27
- package/assets/rules/turn-entry.md +6 -0
- package/assets/samples/tasks/_template/grill.md +5 -0
- package/assets/samples/tasks/_template/plan.md +3 -0
- package/assets/skills/agent-kit.md +99 -76
- package/assets/templates/postmortem.md +5 -1
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +30 -6
- package/bin/agent-kit.js.map +1 -1
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +2 -1
- package/lib/catalog.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +96 -7
- package/lib/commands.js.map +1 -1
- package/lib/hooks-map.d.ts +26 -0
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +58 -2
- package/lib/hooks-map.js.map +1 -1
- package/lib/sections.d.ts +6 -0
- package/lib/sections.d.ts.map +1 -1
- package/lib/sections.js +19 -0
- package/lib/sections.js.map +1 -1
- package/lib/shipment.d.ts +2 -0
- package/lib/shipment.d.ts.map +1 -1
- package/lib/shipment.fixture.d.ts +5 -0
- package/lib/shipment.fixture.d.ts.map +1 -1
- package/lib/shipment.fixture.js +7 -0
- package/lib/shipment.fixture.js.map +1 -1
- package/lib/shipment.js +13 -1
- package/lib/shipment.js.map +1 -1
- package/lib/sync.d.ts +35 -3
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +59 -8
- package/lib/sync.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.17.0.tgz +0 -0
- package/rt-tools-agent-kit-0.16.0.tgz +0 -0
|
@@ -47,18 +47,29 @@ description: Переносимый слой правил агента — за
|
|
|
47
47
|
разложенного хуже целого. Правится либо надстройка здесь, либо сам ресурс — а это работа того
|
|
48
48
|
дерева, где пакет живёт исходниками, и здесь о ней не сказано ничего.
|
|
49
49
|
|
|
50
|
+
**Раскладка — правка дерева, а не служебный вызов:** она переписывает сотни ведомых файлов
|
|
51
|
+
разом, и работа поэтому оформляется до `sync`, по тем же правилам, что и любая другая.
|
|
52
|
+
|
|
53
|
+
**Подъём версии пакета и раскладка едут одним изменением.** Сверка раскладки стоит в гейте
|
|
54
|
+
пуша: редакция, поднятая без раскладки, красит главную ветку и запирает дерево целиком.
|
|
55
|
+
|
|
56
|
+
**Объявление хука раскладка кладёт вместе с самим хуком.** Гард зовёт не файл, а запись в
|
|
57
|
+
настройке агента, и разложенный без неё он снаружи неотличим от работающего: файл лежит,
|
|
58
|
+
коммитится, сверка зелёная — а вызова, ради которого написано его тело, он не видит. Раскладка
|
|
59
|
+
дописывает в настройку запись на каждое событие, которого там нет, и говорит, что дописала.
|
|
60
|
+
Правка только прибавляет: ни одна стоящая запись не переписывается и не снимается, снятое
|
|
61
|
+
деревом не возвращается, а настройку, которую не разобрать как JSON, пакет не трогает вовсе —
|
|
62
|
+
там печатается готовый кусок и запись идёт рукой, как прежде.
|
|
63
|
+
|
|
50
64
|
**Держит это гард места правки, а не память.** Правку файла с шапкой раскладки он отбивает в
|
|
51
|
-
минуту правки и называет адрес: источник, если дерево его держит, иначе надстройку.
|
|
52
|
-
|
|
53
|
-
чужим ходом: отказ приходил тому, кто в этот день правил соседний ресурс. Правит копию не
|
|
54
|
-
только рука: форматтер дерева, дошедший до разложенного файла, переписывает его по-своему, и
|
|
65
|
+
минуту правки и называет адрес: источник, если дерево его держит, иначе надстройку. Правит копию
|
|
66
|
+
не только рука: форматтер дерева, дошедший до разложенного файла, переписывает его по-своему, и
|
|
55
67
|
раскладка читает это ровно как правку руками. Снятие копии гард пропускает: снятый файл
|
|
56
68
|
раскладка кладёт заново, и так эту поломку и чинят.
|
|
57
69
|
|
|
58
70
|
**Надстройка правится по разделу, а не кладётся целиком.** Разделы в неё дописывают разные ветки
|
|
59
|
-
и разные заходы, и положенная целиком она уносит все, которых эта правка не касалась: на их
|
|
60
|
-
молча возвращается пакетный
|
|
61
|
-
больше нет. Держит это второй гард — он отбивает запись поверх непустой надстройки и называет
|
|
71
|
+
и разные заходы, и положенная целиком она уносит все, которых эта правка не касалась: на их
|
|
72
|
+
место молча возвращается пакетный текст. Держит это второй гард — он отбивает запись поверх непустой надстройки и называет
|
|
62
73
|
размер того, что затрут: строки и число разделов. Дописывание в конец и правка по месту проходят.
|
|
63
74
|
|
|
64
75
|
## Команды
|
|
@@ -68,15 +79,43 @@ npx agent-kit doctor # что разложено, что отстало,
|
|
|
68
79
|
npx agent-kit sync # разложить
|
|
69
80
|
npx agent-kit sync --check # ничего не писать, отказать при расхождении
|
|
70
81
|
npx agent-kit stats # чем пользовались, чем ни разу, обо что спотыкались
|
|
82
|
+
npx agent-kit enroll --code <код> # завести дерево в приёме и положить его токен
|
|
71
83
|
npx agent-kit propose # отправить груз в приём: сводку, предложения и разборы
|
|
72
84
|
```
|
|
73
85
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
Часть команд слоя исполняет агент, а не программа: `/feedback` кладёт слово о правилах блоком в
|
|
87
|
+
файл предложений, `/skill-curator` разбирает закрытую задачу, `/next-session` закрывает заход.
|
|
88
|
+
|
|
89
|
+
Команд правки самого пакета здесь нет: они зовутся там, где лежат его ресурсы.
|
|
90
|
+
|
|
91
|
+
## Подъём версии
|
|
92
|
+
|
|
93
|
+
Совпавший заголовок замещает раздел пакета целиком, и всё, что пакет дописал в такой раздел новой
|
|
94
|
+
версией, пропадает молча: раскладка сходится, заголовки совпадают, а утверждений нет. Сверка
|
|
95
|
+
заголовков ловит переименование раздела, а не пополнение, — других свидетелей у потери не бывает.
|
|
96
|
+
|
|
97
|
+
Порядок подъёма поэтому из трёх шагов, и первый идёт до установки.
|
|
98
|
+
|
|
99
|
+
1. **Снимок прежней редакции ресурсов.** Установка стирает её без следа, и сравнить потом не с
|
|
100
|
+
чем.
|
|
77
101
|
|
|
78
|
-
|
|
79
|
-
|
|
102
|
+
```bash
|
|
103
|
+
cp -r node_modules/@rt-tools/agent-kit/assets /tmp/agent-kit-assets-<прежняя версия>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
2. **Установка и раскладка.** Обычным порядком.
|
|
107
|
+
3. **Сверка замещённых разделов по снимку.** Какие разделы замещены, называет `doctor` — строкой
|
|
108
|
+
«замещено надстройками разделов» и перечнем «ресурс · заголовок». Каждый из них читается в
|
|
109
|
+
снимке и в новой редакции: что пакет дописал, дописывается в надстройку руками.
|
|
110
|
+
|
|
111
|
+
Ни `doctor`, ни `sync --check` сами этого не сверяют: прежней редакции у них нет.
|
|
112
|
+
|
|
113
|
+
По каждому названному разделу сверяются статьи, а не заголовки: заголовок как раз и совпал,
|
|
114
|
+
этим раздел замещён. Готовая пара команд — в холодной части рядом.
|
|
115
|
+
|
|
116
|
+
Дальше решение обычное: раздел, ради которого надстройка заводилась, остаётся замещённым, а
|
|
117
|
+
раздел, чья причина ушла с исправленной редакцией, снимается — о том и говорит четвёртая строка
|
|
118
|
+
предложения.
|
|
80
119
|
|
|
81
120
|
## Что пакет везёт, а что остаётся дереву
|
|
82
121
|
|
|
@@ -108,22 +147,20 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
108
147
|
|
|
109
148
|
Слой правил правится не по памяти, а по тому, как им пользовались. Держится это тремя вещами.
|
|
110
149
|
|
|
111
|
-
**Наблюдения** пишут сами гарды — в `.claude/rt-kit/observations/`, файлом на день. В строке
|
|
112
|
-
|
|
113
|
-
|
|
150
|
+
**Наблюдения** пишут сами гарды — в `.claude/rt-kit/observations/`, файлом на день. В строке имя
|
|
151
|
+
ресурса пакета, род события, род правки, версия и признак сессии; путей дерева и его имени там
|
|
152
|
+
нет. Выключаются ключом `"observe": false` в конфиге.
|
|
114
153
|
|
|
115
154
|
**Сводка** — `agent-kit stats`. Самая ценная её строка не «чем пользовались», а **что разложено
|
|
116
155
|
и не загружено ни разу**: правило, которого никто не открыл, ничем себя не выдаёт.
|
|
117
156
|
|
|
118
157
|
**Цена** — `agent-kit cost`. Сводка говорит, чем пользовались; цена — сколько это стоило: вес
|
|
119
|
-
входа в работу, вес одного правила и вес всего слоя. Считается не файл, а то, что заход
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
приносит их пачкой, задним числом. Слово, сказанное посреди работы, кладёт командой `/feedback`
|
|
126
|
-
сам агент: до неё такое слово адреса не получало вовсе и умирало вместе с сессией. Оба пути
|
|
158
|
+
входа в работу, вес одного правила и вес всего слоя. Считается не файл, а то, что заход получает:
|
|
159
|
+
описание приходит полем, словарь и карта хода — выводом хуков. Число сравнимо только со снятым
|
|
160
|
+
той же командой.
|
|
161
|
+
|
|
162
|
+
**Предложения** приходят двумя путями: разбор закрытой задачи — командой `/skill-curator` —
|
|
163
|
+
приносит их пачкой, а слово, сказанное посреди работы, кладёт командой `/feedback` сам агент. Оба
|
|
127
164
|
пишут в один файл дня и в одной форме; в сеть не ходит ни один — увозит их отправка.
|
|
128
165
|
|
|
129
166
|
Каждая запись несёт четыре строки: **место** — куда правка встаёт в ресурсе, **повод** — что
|
|
@@ -132,17 +169,11 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
132
169
|
снимаются, когда правка приедет редакцией пакета.
|
|
133
170
|
|
|
134
171
|
Третья строка — единственная, которую проверяет машина: цитата ищется в ресурсе, и ненайденная
|
|
135
|
-
отбивает блок. Ближайшего нет вовсе — так и пишется: «нет».
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
отметкой «отбито» и причиной: видно, что разбор был, и видно, почему он не стал правкой.
|
|
141
|
-
|
|
142
|
-
Четвёртая пишется затем, что предложение уезжает наружу, а
|
|
143
|
-
надстройка остаётся лежать здесь: без неё дерево не может сказать, какие из его надстроек
|
|
144
|
-
исправленная редакция закрыла, — снять наугад страшно, оставить дёшево, и надстройка остаётся
|
|
145
|
-
навсегда, молча замещая исправленный раздел пакета. Снимать нечего — так и пишется; пустой
|
|
172
|
+
отбивает блок. Ближайшего нет вовсе — так и пишется: «нет». Отбитый блок остаётся лежать с
|
|
173
|
+
отметкой «отбито» и причиной: видно, что разбор был и почему он не стал правкой.
|
|
174
|
+
|
|
175
|
+
Четвёртая пишется затем, что предложение уезжает наружу, а надстройка остаётся лежать здесь:
|
|
176
|
+
без неё она замещает уже исправленный раздел навсегда. Снимать нечего — так и пишется; пустой
|
|
146
177
|
четвёртая строка не бывает.
|
|
147
178
|
|
|
148
179
|
Каждому предложению ставится адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
|
|
@@ -154,35 +185,37 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
154
185
|
это выложено всему свету. Адрес приёма объявляется ключом `intake` в конфиге дерева, токен —
|
|
155
186
|
ключом `token`, и лежит он вне дерева.
|
|
156
187
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
188
|
+
Оба значения приходят от владельца приёма, а не придумываются потребителем: адрес он называет, а токен выдаёт
|
|
189
|
+
одноразовым кодом приглашения — код заводит дерево в приёме и кладёт токен в файл ключа `token`; выданный в админке
|
|
190
|
+
кладётся тем же входом и в сеть не идёт. До приглашения отправка отказывает по устройству, а не по недонастройке.
|
|
191
|
+
|
|
192
|
+
**Признак дерева считает отправитель, а не человек.** Он выводится из адреса репозитория, и
|
|
193
|
+
запись в приёме заводится именно им: дерево, заведённое своим словом, приёмник не узнаёт и
|
|
194
|
+
отвечает отказом на каждой отправке. Что уедет и под каким признаком, печатает прогон вхолостую —
|
|
195
|
+
единственный способ узнать признак до заведения записи.
|
|
196
|
+
|
|
197
|
+
**Отметка об отправке — след для человека, а не хранилище состояния: она говорит, что запись в
|
|
198
|
+
приёме есть, а не что её положил этот вызов.** Чистое дерево после отправки значит, что весь
|
|
199
|
+
груз в приёме уже лежал, а не что отправка не сработала.
|
|
163
200
|
|
|
164
201
|
Разбирают их там, где лежат правимые ресурсы и видно всех потребителей сразу, — а сюда
|
|
165
202
|
приезжает ответ приёма о том, сколько записей легло.
|
|
166
203
|
|
|
167
|
-
**Имя файла предложения в текстах дерева не называется.**
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
отправлено и о чём оно; ресурс пакета при этом называть можно — он в истории есть.
|
|
204
|
+
**Имя файла предложения в текстах дерева не называется.** Читателю чужого дерева оно не даёт
|
|
205
|
+
ничего, а там, где каталог остаётся на машине автора, ссылка ведёт в пустоту и проверка путей
|
|
206
|
+
краснеет. Текст репозитория говорит, кому предложение отправлено и о чём оно; ресурс пакета
|
|
207
|
+
при этом называть можно — он в истории есть.
|
|
172
208
|
|
|
173
|
-
Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
считают дырку закрытой.
|
|
209
|
+
Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой не
|
|
210
|
+
приходит; цитата не становится правилом от того, что её произнесли. Закрытым предложение
|
|
211
|
+
считается, только войдя в ресурс пакета: до этого на него не ссылаются как на действующее
|
|
212
|
+
требование и не считают дырку закрытой.
|
|
178
213
|
|
|
179
214
|
**Слово владельца о предложении — «отправь», «заведи», «напиши пропозал» и любая другая форма
|
|
180
215
|
того же — исполняется отправкой в тот же ход.** Сухой прогон отправкой не является: он
|
|
181
|
-
показывает, что уехало бы, ничего не заводит и следа наружу не оставляет.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
отложить. Стережёт это гард предложения на завершении хода — там же, где стоит гард
|
|
185
|
-
происшествия, и по той же причине.
|
|
216
|
+
показывает, что уехало бы, ничего не заводит и следа наружу не оставляет. Отметки, которыми
|
|
217
|
+
отправка пачкает дерево, ложатся вторым коммитом в ту же ветку — это их место, а не повод
|
|
218
|
+
отложить. Стережёт это гард предложения на завершении хода.
|
|
186
219
|
|
|
187
220
|
## Установка туда, где уже всё своё
|
|
188
221
|
|
|
@@ -206,42 +239,32 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
206
239
|
|
|
207
240
|
- **Молчание требованию не отвечает.** Дерево с пустым `has` не получает ни одного помеченного
|
|
208
241
|
ресурса: положенный наугад, он вернётся пустым компаньоном, заполнить который нечем.
|
|
209
|
-
- **Требование — не вид.** Вид
|
|
210
|
-
сразу несколько, и дерево, которое публикует пакеты и держит приложение, называет оба.
|
|
211
|
-
- **`only` сильнее требования.** Ресурс, названный поимённо, ложится и при неотвеченном
|
|
212
|
-
требовании; перечень раскладки называет это вслух, а отказ по его пустому компаньону зовёт
|
|
213
|
-
снять ресурс, а не заполнять черновик.
|
|
214
|
-
- **Свойство, которого пакет не объявлял, роняет раскладку** — что в `has` дерева, что в имени
|
|
215
|
-
ресурса. Объявлены свойства перечнем при пакете, рядом с осями различия.
|
|
242
|
+
- **Требование — не вид.** Вид выбирается один; свойств у дерева сразу несколько.
|
|
216
243
|
|
|
217
244
|
## Выключенная роль
|
|
218
245
|
|
|
219
|
-
Роль, при которой стоит гард, зовётся не по усмотрению исполнителя: гард держит работу, пока
|
|
220
|
-
|
|
221
|
-
`rolesOff` — именем файла роли без расширения.
|
|
246
|
+
Роль, при которой стоит гард, зовётся не по усмотрению исполнителя: гард держит работу, пока роль
|
|
247
|
+
не сказала своё. Дерево, которому она мешает, называет её ключом `rolesOff` — именем файла роли.
|
|
222
248
|
|
|
223
249
|
```json
|
|
224
250
|
{ "rolesOff": ["strict-teacher"] }
|
|
225
251
|
```
|
|
226
252
|
|
|
227
253
|
- **Выключается обязательность вызова, а не роль.** Файл роли остаётся разложенным, и позвать её
|
|
228
|
-
руками можно в любую минуту. Список читают сами гарды — помощником,
|
|
229
|
-
рядом; собственного объявления события у него нет, к действиям агента он не подключается.
|
|
254
|
+
руками можно в любую минуту. Список читают сами гарды — помощником, лежащим рядом с ними.
|
|
230
255
|
- **От отказа ключом `skip` это отличается тем, что ничего не убирает.** Отказ не кладёт файл
|
|
231
256
|
роли вовсе: звать становится некого, а гард при ней остаётся лежать и продолжает отбивать.
|
|
232
257
|
Здесь наоборот — роль на месте, молчит гард.
|
|
233
|
-
- **Настройка, которую не прочитать, роль не выключает.** Не нашлось `jq`, нет настройки, в
|
|
234
|
-
настройке сломан разбор — гард судит, как судил. Обратный выбор гасил бы слой правил молча, и
|
|
235
|
-
заметить это было бы нечем.
|
|
236
|
-
- **Ключ, написанный не списком, ловит раскладка, а не гард.** Гарду виден только список имён:
|
|
237
|
-
строка вместо списка читается им как «роль включена», и роль работает, хотя дерево считает её
|
|
238
|
-
выключенной. Отказывает на этом разбор настройки — первой же раскладкой, называя ключ.
|
|
239
|
-
- **Выключение живёт в настройке дерева, а не в настройке агента.** Строка, вырезанная из
|
|
240
|
-
настроек агента руками, теряется на первой же правке того файла, и вернуть роль будет нечем.
|
|
241
|
-
Здесь оно объявлено в одном месте и видно всякому, кто читает настройку дерева.
|
|
242
258
|
|
|
243
259
|
## Ловушки раскладки
|
|
244
260
|
|
|
261
|
+
- **Запись файла командой оболочки судится по всем путям, названным в её теле.** Гейт вынимает
|
|
262
|
+
пути из текста команды, а тело документа читает целиком, как только в команде встречается имя
|
|
263
|
+
интерпретатора, — и строка запуска первой строкой записываемого файла возвращает его туда сама.
|
|
264
|
+
Строка импорта разложенного модуля требует тогда правило пакетного слоя наравне с правилом
|
|
265
|
+
самого файла, а требуется за раз одно: два отказа подряд, и каждый уносит уже написанное тело.
|
|
266
|
+
Инструмент правки судится одним своим путём и переписывать тело не заставляет; перенаправление
|
|
267
|
+
оболочки остаётся для того, что файлом дерева не станет.
|
|
245
268
|
- **Своё, стоящее рядом с разложенным, повторяет его механику молча.** Проверка, гард и утилита
|
|
246
269
|
дерева лежат в тех же каталогах, что и пакетные, а общий разбор списка известного, корни
|
|
247
270
|
исходников, список пропускаемых каталогов и снимок долга приезжают модулем настройки проверок.
|
|
@@ -29,4 +29,8 @@
|
|
|
29
29
|
## Что ушло в слой правил
|
|
30
30
|
|
|
31
31
|
<Предложение с адресом либо правка закона, правила, паттерна — с именами. Запись без этого
|
|
32
|
-
раздела закрытой не считается: разбор, из которого ничего не вышло, —
|
|
32
|
+
раздела закрытой не считается: разбор, из которого ничего не вышло, — жалоба.
|
|
33
|
+
|
|
34
|
+
Предложение называется адресом и предметом — «в пакет, о таком-то», — а не путём к файлу
|
|
35
|
+
предложений: каталог предложений в историю не едет, и путь у любого другого читателя ведёт в
|
|
36
|
+
пустоту. Ресурс, к которому предложение написано, называть можно: он в истории есть.>
|
package/bin/agent-kit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AAoW7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU9E"}
|
package/bin/agent-kit.js
CHANGED
|
@@ -85,19 +85,40 @@ function environmentOf(root) {
|
|
|
85
85
|
stale: staleBuild(pkg, manifest.name),
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
|
-
/**
|
|
89
|
-
function
|
|
88
|
+
/** Вывод git в этом дереве. Отказ и пустота здесь одно и то же: адреса нет — и это не отказ. */
|
|
89
|
+
function gitSays(root, args) {
|
|
90
90
|
try {
|
|
91
91
|
// eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым
|
|
92
|
-
return execFileSync('git', ['-C', root, '
|
|
93
|
-
encoding: 'utf8',
|
|
94
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
95
|
-
}).trim();
|
|
92
|
+
return execFileSync('git', ['-C', root, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
96
93
|
}
|
|
97
94
|
catch {
|
|
98
95
|
return '';
|
|
99
96
|
}
|
|
100
97
|
}
|
|
98
|
+
/** Имена удалённых репозиториев этого дерева, по одному в строке. */
|
|
99
|
+
function remoteNames(root) {
|
|
100
|
+
return gitSays(root, ['remote'])
|
|
101
|
+
.split('\n')
|
|
102
|
+
.map((name) => name.trim())
|
|
103
|
+
.filter(Boolean);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ.
|
|
107
|
+
*
|
|
108
|
+
* Имя `origin` — соглашение, а не устройство: рабочая копия, назвавшая свои remotes по хостам,
|
|
109
|
+
* на которые смотрит, оставалась без адреса вовсе, и отправка отказывала словами «удалённого
|
|
110
|
+
* репозитория нет» — при том что репозиторий у неё есть, и не один. Порядок поэтому такой:
|
|
111
|
+
* `origin`, если он есть; ровно один remote — он; несколько без `origin` — адреса нет, и выбор
|
|
112
|
+
* за человеком. Угадать здесь нельзя: угаданное неверно сливает в сводке приёма два дерева в
|
|
113
|
+
* одно, а увидеть это нечем.
|
|
114
|
+
*/
|
|
115
|
+
function remoteOf(root) {
|
|
116
|
+
const names = remoteNames(root);
|
|
117
|
+
if (names.includes('origin')) {
|
|
118
|
+
return gitSays(root, ['remote', 'get-url', 'origin']);
|
|
119
|
+
}
|
|
120
|
+
return names.length === 1 ? gitSays(root, ['remote', 'get-url', names[0]]) : '';
|
|
121
|
+
}
|
|
101
122
|
function optionOf(argv, name, fallback) {
|
|
102
123
|
const index = argv.indexOf(name);
|
|
103
124
|
return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;
|
|
@@ -252,6 +273,9 @@ async function runPropose(env, argv) {
|
|
|
252
273
|
dryRun: argv.includes('--dry-run'),
|
|
253
274
|
ship: httpShip,
|
|
254
275
|
remote: remoteOf(env.root),
|
|
276
|
+
// Имена доезжают до отказа: выбор за человеком, и отказ, не назвавший, из чего выбирать,
|
|
277
|
+
// отправляет его смотреть то же самое своими руками.
|
|
278
|
+
remotes: remoteNames(env.root),
|
|
255
279
|
// Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.
|
|
256
280
|
days: DEFAULT_DAYS,
|
|
257
281
|
today: new Date().toISOString().slice(0, 10),
|
package/bin/agent-kit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { CONFIG_PATH, IConfig, readConfig } from '../lib/config.js';\nimport { costLines, costOf, CostUnavailableError, ICost } from '../lib/cost.js';\nimport { enroll, httpEnroll } from '../lib/enroll.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose, treeSlugOf } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' cost посчитать цену контекста: вход в работу, одно правило, весь слой',\n ' cost --rule <имя> какое правило взвесить; без довода берётся самое тяжёлое',\n ' cost --json то же машиночитаемо — этим числа кладут в замысел',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n ' enroll --code <код> завести дерево по приглашению владельца: обмен кода на токен',\n ' enroll --token <токен> завести дерево токеном, выданным в админке приёма; в сеть не идёт',\n ' enroll --force перезаписать уже лежащий токен намеренно',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\n // eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым\n return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n } catch {\n return '';\n }\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantOfAxis(axis: IAxis, argv: readonly string[]): Promise<string | null | IOutcomeOfCommand> {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const values: readonly string[] = axis.options.map((option: IOptionOfAxis): string => option.value);\n\n if (spoken) {\n return values.includes(spoken)\n ? spoken\n : {\n code: 1,\n lines: [`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`, `есть: ${values.join(', ')}`],\n };\n }\n\n if (argv.includes('--all')) {\n return axis.options[0]?.value ?? '';\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: ['спросить некого: запуск без терминала', `назови вид флагом \\`--${axis.name} <вид>\\`: ${values.join(', ')}`],\n };\n }\n\n return askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n}\n\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const answer: string | null | IOutcomeOfCommand = await variantOfAxis(axis, argv);\n\n if (isOutcome(answer)) {\n return answer;\n }\n\n if (answer === null) {\n return null;\n }\n\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\n/** Заведение настройки: выбор ресурсов и видов, брошенный выбор ничего не пишет. */\nasync function runInit(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n}\n\n/**\n * Цена контекста: три веса и то, чем они сняты.\n *\n * Отказ печатается тем же выводом, а не броском: команду зовут глазами, и трассировка стека\n * говорит ей читателю меньше, чем строка о том, чего в дереве нет.\n */\nfunction runCost(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const named: string = optionOf(argv, '--rule', '');\n let cost: ICost;\n try {\n cost = costOf(env.root, named === '' ? null : named);\n } catch (failure: unknown) {\n if (failure instanceof CostUnavailableError) {\n return { code: 1, lines: [failure.message] };\n }\n throw failure;\n }\n\n return { code: 0, lines: [...costLines(cost, argv.includes('--json'))] };\n}\n\n/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\nfunction runStats(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n}\n\n/**\n * Отправка накопленного.\n *\n * Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый довод её\n * кончает, а не пропускается молча: вызов ради списка режимов отправил в приём всё накопленное, и\n * по выводу это не отличалось от «команда ничего не сделала». Прочие команды такого разбора не\n * знают — их действие обратимо.\n */\nasync function runPropose(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n}\n\n/** Приписка дерева к приёмнику по коду приглашения. */\nasync function runEnroll(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const config: IConfig | null = readConfig(env.root);\n\n if (!config) {\n return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \\`init\\``] };\n }\n\n return enroll({\n root: env.root,\n intake: config.intake,\n code: optionOf(argv, '--code', ''),\n issued: optionOf(argv, '--token', ''),\n tree: treeSlugOf(remoteOf(env.root), config.tree),\n token: config.token,\n force: argv.includes('--force'),\n call: httpEnroll,\n });\n}\n\n/** Ветка команды: окружение и доводы строки запуска на входе, вывод и код возврата на выходе. */\ntype TCommandRun = (env: IEnvironment, argv: readonly string[]) => IOutcomeOfCommand | Promise<IOutcomeOfCommand>;\n\n/** Что делает каждая команда строки запуска. Ключ — слово, которым её зовут. */\nconst COMMANDS: Readonly<Record<string, TCommandRun>> = {\n init: runInit,\n list: (env: IEnvironment): IOutcomeOfCommand => list(env),\n sync: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand => sync(env, argv.includes('--check')),\n cost: runCost,\n stats: runStats,\n propose: runPropose,\n enroll: runEnroll,\n doctor: (env: IEnvironment): IOutcomeOfCommand => doctor(env),\n adopt: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand =>\n adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n ),\n};\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n const run: TCommandRun | undefined = Object.hasOwn(COMMANDS, command) ? COMMANDS[command] : undefined;\n\n if (!run) {\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n\n return run(env, argv);\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
|
|
1
|
+
{"version":3,"file":"agent-kit.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Точка входа. Разбирает аргументы, добывает выбор проекта, зовёт команду и печатает то, что\n * она вернула. Своей работы у неё нет: всё, что решает, живёт в `commands.ts` и проверяется\n * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки\n * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.\n */\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport process from 'node:process';\n\nimport { unknownFlagsIn } from '../lib/argv.js';\nimport { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, stats, sync } from '../lib/commands.js';\nimport { CONFIG_PATH, IConfig, readConfig } from '../lib/config.js';\nimport { costLines, costOf, CostUnavailableError, ICost } from '../lib/cost.js';\nimport { enroll, httpEnroll } from '../lib/enroll.js';\nimport { httpShip } from '../lib/ship.js';\nimport { propose, treeSlugOf } from '../lib/shipment.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { staleBuild } from '../lib/freshness.js';\nimport { packageRootFrom } from '../lib/package-root.js';\nimport { IChoice } from '../lib/picker.js';\nimport { IAxis, IOptionOfAxis, readAxes } from '../lib/variants.js';\nimport { ask, askOne, canAsk } from './prompt.js';\n\nconst USAGE: readonly string[] = [\n 'agent-kit <команда>',\n '',\n ' init завести .claude/rt-kit.json и каталог надстроек',\n ' list что везёт пакет и что из этого взято здесь',\n ' sync разложить ресурсы пакета в дерево проекта',\n ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',\n ' doctor рассказать о состоянии раскладки, ничего не меняя',\n ' cost посчитать цену контекста: вход в работу, одно правило, весь слой',\n ' cost --rule <имя> какое правило взвесить; без довода берётся самое тяжёлое',\n ' cost --json то же машиночитаемо — этим числа кладут в замысел',\n ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',\n ' stats --days N за сколько дней; без довода — за три',\n ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',\n ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',\n ' enroll --code <код> завести дерево по приглашению владельца: обмен кода на токен',\n ' enroll --token <токен> завести дерево токеном, выданным в админке приёма; в сеть не идёт',\n ' enroll --force перезаписать уже лежащий токен намеренно',\n '',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n '',\n 'Выбор законов при `init`:',\n '',\n ' --all взять все законы, ни о чём не спрашивая',\n ' --laws a,b,c взять только названные; имена — из `agent-kit list`',\n ' без обоих спросить галочками; без терминала — отказ',\n '',\n 'Вид ресурсов при `init` — там, где один закон исполняется разными командами:',\n '',\n ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',\n ' без флага спросить; без терминала — отказ, кроме `--all`',\n];\n\n/**\n * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без\n * пометки этот путь читался бы как ещё один незнакомый довод.\n */\nconst PROPOSE_FLAGS: readonly string[] = ['--dry-run', '--root <>'];\n\n/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */\nconst PROPOSE_USAGE: readonly string[] = [\n ' propose отправить груз в приём',\n ' propose --dry-run показать, что уехало бы, и ничего не отправлять',\n ' --root <путь> корень проекта; по умолчанию текущий каталог',\n];\n\n/**\n * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только\n * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,\n * разбирающий модули как CommonJS, на них уже не спотыкается.\n */\nfunction environmentOf(root: string): IEnvironment {\n const pkg: string = packageRootFrom(dirname(fileURLToPath(import.meta.url)));\n const manifest: { name: string; version: string } = JSON.parse(readFileSync(join(pkg, 'package.json'), 'utf8')) as {\n name: string;\n version: string;\n };\n\n return {\n root,\n version: manifest.version,\n assetsDir: join(pkg, 'assets'),\n // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.\n // У потребителя исходников рядом нет, и сверка молчит.\n stale: staleBuild(pkg, manifest.name),\n };\n}\n\n/** Вывод git в этом дереве. Отказ и пустота здесь одно и то же: адреса нет — и это не отказ. */\nfunction gitSays(root: string, args: readonly string[]): string {\n try {\n // eslint-disable-next-line sonarjs/no-os-command-from-path -- путь к git у каждой машины свой, и прибитый здесь сделал бы пакет непереносимым\n return execFileSync('git', ['-C', root, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n } catch {\n return '';\n }\n}\n\n/** Имена удалённых репозиториев этого дерева, по одному в строке. */\nfunction remoteNames(root: string): readonly string[] {\n return gitSays(root, ['remote'])\n .split('\\n')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n}\n\n/**\n * Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ.\n *\n * Имя `origin` — соглашение, а не устройство: рабочая копия, назвавшая свои remotes по хостам,\n * на которые смотрит, оставалась без адреса вовсе, и отправка отказывала словами «удалённого\n * репозитория нет» — при том что репозиторий у неё есть, и не один. Порядок поэтому такой:\n * `origin`, если он есть; ровно один remote — он; несколько без `origin` — адреса нет, и выбор\n * за человеком. Угадать здесь нельзя: угаданное неверно сливает в сводке приёма два дерева в\n * одно, а увидеть это нечем.\n */\nfunction remoteOf(root: string): string {\n const names: readonly string[] = remoteNames(root);\n\n if (names.includes('origin')) {\n return gitSays(root, ['remote', 'get-url', 'origin']);\n }\n\n return names.length === 1 ? gitSays(root, ['remote', 'get-url', names[0]]) : '';\n}\n\nfunction optionOf(argv: readonly string[], name: string, fallback: string): string {\n const index: number = argv.indexOf(name);\n\n return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;\n}\n\nconst isOutcome: (value: unknown) => value is IOutcomeOfCommand = (value: unknown): value is IOutcomeOfCommand =>\n typeof value === 'object' && value !== null && 'code' in value;\n\n/**\n * Выбор законов для `init`: список идентификаторов, `null` на брошенном выборе или готовый\n * отказ. Пустой список означает «взять всё», поэтому брошенный выбор отличается от него не\n * значением, а `null`: подставить «всё» вместо неотвеченного вопроса значило бы разложить\n * пятнадцать законов тому, кто как раз просил спросить.\n */\nasync function selectionFor(argv: readonly string[], assetsDir: string): Promise<readonly string[] | null | IOutcomeOfCommand> {\n if (argv.includes('--all')) {\n return [];\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const spoken: string = optionOf(argv, '--laws', '');\n\n if (spoken) {\n const named: string[] = spoken\n .split(',')\n .map((name: string): string => name.trim())\n .filter(Boolean);\n const { ids, unknown } = resolveSelection(named, 'laws', catalog);\n\n return unknown.length\n ? { code: 1, lines: [`таких законов пакет не везёт: ${unknown.join(', ')}`, 'что везёт — `agent-kit list`'] }\n : ids;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n 'назови законы флагом `--laws a,b,c` или возьми все флагом `--all`',\n 'что везёт пакет — `agent-kit list`',\n ],\n };\n }\n\n const choices: readonly IChoice[] = catalog\n .filter((entry: IEntryOfCatalog): boolean => entry.kind === 'laws')\n .map((entry: IEntryOfCatalog): IChoice => ({ id: entry.id, name: entry.name, title: entry.title }));\n\n return ask(choices, 'Какие законы разложить в этом проекте?');\n}\n\n/**\n * Виды для `init` по осям, объявленным пакетом: что взято из флага, что спрошено.\n *\n * `--all` берёт первый объявленный вид оси и **говорит об этом**: в CI спрашивать некого, а\n * отказ там означал бы, что пакет нельзя разложить без человека. Первый вид — умолчание, а не\n * догадка: порядок в объявлении оси и есть порядок предпочтения.\n */\nasync function variantOfAxis(axis: IAxis, argv: readonly string[]): Promise<string | null | IOutcomeOfCommand> {\n const spoken: string = optionOf(argv, `--${axis.name}`, '');\n const values: readonly string[] = axis.options.map((option: IOptionOfAxis): string => option.value);\n\n if (spoken) {\n return values.includes(spoken)\n ? spoken\n : {\n code: 1,\n lines: [`такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`, `есть: ${values.join(', ')}`],\n };\n }\n\n if (argv.includes('--all')) {\n return axis.options[0]?.value ?? '';\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: ['спросить некого: запуск без терминала', `назови вид флагом \\`--${axis.name} <вид>\\`: ${values.join(', ')}`],\n };\n }\n\n return askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n}\n\nasync function variantsFor(argv: readonly string[], assetsDir: string): Promise<Record<string, string> | null | IOutcomeOfCommand> {\n const axes: readonly IAxis[] = readAxes(assetsDir);\n const chosen: Record<string, string> = {};\n\n for (const axis of axes) {\n const answer: string | null | IOutcomeOfCommand = await variantOfAxis(axis, argv);\n\n if (isOutcome(answer)) {\n return answer;\n }\n\n if (answer === null) {\n return null;\n }\n\n chosen[axis.name] = answer;\n }\n\n return chosen;\n}\n\n/** Заведение настройки: выбор ресурсов и видов, брошенный выбор ничего не пишет. */\nasync function runInit(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const selection: readonly string[] | null | IOutcomeOfCommand = await selectionFor(argv, env.assetsDir);\n if (isOutcome(selection)) {\n return selection;\n }\n if (selection === null) {\n return { code: 1, lines: ['выбор брошен — ничего не заведено'] };\n }\n\n const variants: Record<string, string> | null | IOutcomeOfCommand = await variantsFor(argv, env.assetsDir);\n if (isOutcome(variants)) {\n return variants;\n }\n\n return variants === null\n ? { code: 1, lines: ['выбор брошен — ничего не заведено'] }\n : init(env.root, selection, variants, env.assetsDir);\n}\n\n/**\n * Цена контекста: три веса и то, чем они сняты.\n *\n * Отказ печатается тем же выводом, а не броском: команду зовут глазами, и трассировка стека\n * говорит ей читателю меньше, чем строка о том, чего в дереве нет.\n */\nfunction runCost(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const named: string = optionOf(argv, '--rule', '');\n let cost: ICost;\n try {\n cost = costOf(env.root, named === '' ? null : named);\n } catch (failure: unknown) {\n if (failure instanceof CostUnavailableError) {\n return { code: 1, lines: [failure.message] };\n }\n throw failure;\n }\n\n return { code: 0, lines: [...costLines(cost, argv.includes('--json'))] };\n}\n\n/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\nfunction runStats(env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand {\n const spoken: number = Number(optionOf(argv, '--days', ''));\n\n return stats(env, {\n days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,\n // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за\n // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.\n today: new Date().toISOString().slice(0, 10),\n json: argv.includes('--json'),\n });\n}\n\n/**\n * Отправка накопленного.\n *\n * Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый довод её\n * кончает, а не пропускается молча: вызов ради списка режимов отправил в приём всё накопленное, и\n * по выводу это не отличалось от «команда ничего не сделала». Прочие команды такого разбора не\n * знают — их действие обратимо.\n */\nasync function runPropose(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);\n if (unknown.length) {\n return {\n code: 1,\n lines: [`таких доводов у \\`propose\\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],\n };\n }\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n ship: httpShip,\n remote: remoteOf(env.root),\n // Имена доезжают до отказа: выбор за человеком, и отказ, не назвавший, из чего выбирать,\n // отправляет его смотреть то же самое своими руками.\n remotes: remoteNames(env.root),\n // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n });\n}\n\n/** Приписка дерева к приёмнику по коду приглашения. */\nasync function runEnroll(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const config: IConfig | null = readConfig(env.root);\n\n if (!config) {\n return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \\`init\\``] };\n }\n\n return enroll({\n root: env.root,\n intake: config.intake,\n code: optionOf(argv, '--code', ''),\n issued: optionOf(argv, '--token', ''),\n tree: treeSlugOf(remoteOf(env.root), config.tree),\n token: config.token,\n force: argv.includes('--force'),\n call: httpEnroll,\n });\n}\n\n/** Ветка команды: окружение и доводы строки запуска на входе, вывод и код возврата на выходе. */\ntype TCommandRun = (env: IEnvironment, argv: readonly string[]) => IOutcomeOfCommand | Promise<IOutcomeOfCommand>;\n\n/** Что делает каждая команда строки запуска. Ключ — слово, которым её зовут. */\nconst COMMANDS: Readonly<Record<string, TCommandRun>> = {\n init: runInit,\n list: (env: IEnvironment): IOutcomeOfCommand => list(env),\n sync: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand => sync(env, argv.includes('--check')),\n cost: runCost,\n stats: runStats,\n propose: runPropose,\n enroll: runEnroll,\n doctor: (env: IEnvironment): IOutcomeOfCommand => doctor(env),\n adopt: (env: IEnvironment, argv: readonly string[]): IOutcomeOfCommand =>\n adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n ),\n};\n\nexport async function main(argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const command: string = argv[0] ?? '';\n const env: IEnvironment = environmentOf(resolve(optionOf(argv, '--root', process.cwd())));\n const run: TCommandRun | undefined = Object.hasOwn(COMMANDS, command) ? COMMANDS[command] : undefined;\n\n if (!run) {\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\n\n return run(env, argv);\n}\n\nconst outcome: IOutcomeOfCommand = await main(process.argv.slice(2));\nfor (const line of outcome.lines) {\n // eslint-disable-next-line no-console\n console.log(line);\n}\nprocess.exit(outcome.code);\n"]}
|
package/lib/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/catalog.ts"],"names":[],"mappings":"AAUA,OAAO,EAAS,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/catalog.ts"],"names":[],"mappings":"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"}
|
package/lib/catalog.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { accessSync, constants, readdirSync, readFileSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { KINDS } from './config.js';
|
|
11
|
+
import { linesOutsideFences } from './sections.js';
|
|
11
12
|
import { answersRequirement, requirementOf, withoutRequirement } from './traits.js';
|
|
12
13
|
import { matchesVariant, readAxes, variantOf, withoutVariant } from './variants.js';
|
|
13
14
|
const TITLE = /^#\s+(\S.*)$/m;
|
|
@@ -49,7 +50,7 @@ const REQUIRES = /^(?:#[^\S\n]*Требует:|\*\*Требует:\*\*)([^\n]*)$
|
|
|
49
50
|
* ненайденного.
|
|
50
51
|
*/
|
|
51
52
|
export function requiresOf(text) {
|
|
52
|
-
const found = REQUIRES.exec(text);
|
|
53
|
+
const found = REQUIRES.exec(linesOutsideFences(text).join('\n'));
|
|
53
54
|
if (!found) {
|
|
54
55
|
return [];
|
|
55
56
|
}
|