@rt-tools/agent-kit 0.11.0 → 0.12.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/check-file-size.mjs +19 -4
- package/assets/checks/check-state-next.mjs +10 -2
- package/assets/checks/rt-kit-checks.config.mjs +16 -2
- package/assets/defaults/project.sh +9 -1
- package/assets/defaults/turn-map.md +8 -6
- package/assets/hooks/browser-guard-device-id.sh +3 -1
- package/assets/hooks/browser-guard-no-asking.sh +3 -1
- package/assets/hooks/browser-guard-no-other-drivers.sh +5 -3
- package/assets/hooks/browser-guard-require-select.sh +4 -2
- package/assets/hooks/claim-guard.sh +3 -1
- package/assets/hooks/conscience-guard.sh +3 -1
- package/assets/hooks/dev-server-guard.sh +5 -3
- package/assets/hooks/dispatch.sh +69 -0
- package/assets/hooks/docs-guard.sh +6 -4
- package/assets/hooks/exam-guard.sh +5 -3
- package/assets/hooks/git-guard-delivery.sh +37 -5
- package/assets/hooks/git-guard-main.sh +6 -4
- package/assets/hooks/git-guard-push-tests.sh +6 -4
- package/assets/hooks/grill-gate.sh +4 -2
- package/assets/hooks/handoff-entry-guard.sh +4 -2
- package/assets/hooks/handoff-write.sh +27 -6
- package/assets/hooks/hook-input.sh +54 -0
- package/assets/hooks/lint-after-edit.sh +5 -3
- package/assets/hooks/postmortem-guard.sh +3 -1
- package/assets/hooks/proposal-guard.sh +3 -1
- package/assets/hooks/prose-style-guard.sh +5 -3
- package/assets/hooks/qa-dataid-guard.sh +4 -2
- package/assets/hooks/rerun-guard.sh +5 -3
- package/assets/hooks/reuse-first-guard.sh +5 -3
- package/assets/hooks/rule-article.sh +99 -0
- package/assets/hooks/skill-gate-rearm.sh +3 -1
- package/assets/hooks/skill-gate.sh +23 -2
- package/assets/hooks/skill-loaded.sh +3 -1
- package/assets/hooks/sql-guard-request.sh +2 -1
- package/assets/hooks/sql-guard.sh +4 -2
- package/assets/hooks/task-flow-guard.sh +6 -4
- package/assets/hooks/turn-exit-guard.sh +42 -17
- package/assets/hooks/waiting-turn-guard.sh +3 -1
- package/assets/hooks/window-fill-guard.sh +6 -4
- package/assets/laws/work-conduct.md +5 -9
- package/assets/patterns/dependencies-upgrade.md +1 -1
- package/assets/patterns/doc-style-write.md +3 -3
- package/assets/patterns/git-workflow-commit.azure.md +2 -202
- package/assets/patterns/git-workflow-commit.github.md +2 -258
- package/assets/patterns/git-workflow-commit.gitlab.md +1 -217
- package/assets/patterns/git-workflow-docker.md +3 -3
- package/assets/patterns/git-workflow-merge.md +3 -2
- package/assets/patterns/git-workflow-migration.md +3 -3
- package/assets/patterns/git-workflow-pr.azure.md +224 -0
- package/assets/patterns/git-workflow-pr.github.md +280 -0
- package/assets/patterns/git-workflow-pr.gitlab.md +240 -0
- package/assets/patterns/git-workflow-restart.md +3 -3
- package/assets/patterns/git-workflow-secrets.md +3 -3
- package/assets/patterns/task-flow-archive.md +193 -0
- package/assets/patterns/task-flow-close.md +3 -173
- package/assets/patterns/task-flow-handoff.md +4 -4
- package/assets/pitfalls/doc-style.md +80 -0
- package/assets/pitfalls/git-workflow.azure.md +50 -0
- package/assets/pitfalls/git-workflow.github.md +78 -0
- package/assets/pitfalls/git-workflow.gitlab.md +49 -0
- package/assets/pitfalls/spec-driven.md +36 -0
- package/assets/pitfalls/styling-bem.md +45 -0
- package/assets/pitfalls/task-flow.md +62 -0
- package/assets/pitfalls/testing.md +70 -0
- package/assets/rules/deploy-flow.azure.md +106 -0
- package/assets/rules/deploy-flow.github.md +113 -0
- package/assets/rules/deploy-flow.gitlab.md +108 -0
- package/assets/rules/doc-style.md +25 -76
- package/assets/rules/git-workflow.azure.md +6 -92
- package/assets/rules/git-workflow.github.md +14 -127
- package/assets/rules/git-workflow.gitlab.md +6 -93
- package/assets/rules/spec-driven.md +39 -30
- package/assets/rules/styling-bem.md +20 -39
- package/assets/rules/task-flow.md +17 -199
- package/assets/rules/testing.md +3 -64
- package/assets/rules/turn-conduct.md +206 -0
- package/assets/rules/typescript-conventions.md +15 -0
- package/assets/skills/agent-kit.md +35 -12
- package/assets/templates/pitfalls.md +10 -0
- package/assets/templates/rule.md +5 -3
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +1 -42
- package/bin/agent-kit.js.map +1 -1
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +6 -1
- package/lib/assets.js.map +1 -1
- package/lib/cascade.d.ts.map +1 -1
- package/lib/cascade.js +19 -1
- package/lib/cascade.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +1 -0
- package/lib/commands.js.map +1 -1
- package/lib/config.d.ts +16 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +8 -0
- package/lib/config.js.map +1 -1
- package/lib/hooks-map.d.ts +13 -0
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +33 -1
- package/lib/hooks-map.js.map +1 -1
- package/lib/ship.d.ts +1 -2
- package/lib/ship.d.ts.map +1 -1
- package/lib/ship.js +0 -54
- package/lib/ship.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.12.0.tgz +0 -0
- package/assets/commands/agent-kit-digest.md +0 -89
- package/assets/commands/rules-review.md +0 -98
- package/assets/patterns/cargo-triage-mark.md +0 -119
- package/assets/rules/cargo-triage.md +0 -126
- package/lib/cargo-state.d.ts +0 -62
- package/lib/cargo-state.d.ts.map +0 -1
- package/lib/cargo-state.js +0 -118
- package/lib/cargo-state.js.map +0 -1
- package/rt-tools-agent-kit-0.11.0.tgz +0 -0
|
@@ -50,15 +50,23 @@ flowchart TD
|
|
|
50
50
|
|
|
51
51
|
- **Род объявления виден по префиксу имени, и это держат три правила линтера.** У интерфейса,
|
|
52
52
|
у типа и у перечисления свои; все три подняты для всех `.ts`.
|
|
53
|
+
<!-- rt-when: *.ts -->
|
|
54
|
+
|
|
53
55
|
- **Источник, за которым следят, назван суффиксом.** Субъект и наблюдаемое, поднятое из него,
|
|
54
56
|
различаются в месте использования, а не переходом к объявлению.
|
|
57
|
+
<!-- rt-when: *.ts -->
|
|
58
|
+
|
|
55
59
|
- **Суффикс имени файла находит в нём обещанное объявление.** Список суффиксов закрыт: слово,
|
|
56
60
|
которого в нём нет, суффиксом не считается, и такой файл правило не судит.
|
|
61
|
+
<!-- rt-when: *.ts -->
|
|
62
|
+
|
|
57
63
|
- **Файл не длиннее 500 строк, и считаются все строки — пустые и комментарии тоже.** Файл,
|
|
58
64
|
который не влезает на экран целиком, читают по частям, и правку в нём делают, не увидев
|
|
59
65
|
остального. Для `.ts` это держит правило линтера; файлы обвязки — сценарии и скрипты — до
|
|
60
66
|
него не доходят и судятся отдельной проверкой дерева. Накопленное к дню включения
|
|
61
67
|
перечислено поимённо, и строка оттуда снимается вместе с делением своего файла.
|
|
68
|
+
<!-- rt-when: *.ts -->
|
|
69
|
+
|
|
62
70
|
- **Значение из закрытого набора приходит перечислением `E<Имя>`, а не строкой или числом в
|
|
63
71
|
месте использования.** Ключ переводимого поля, имя вкладки, слот обложки, вид записи — всё
|
|
64
72
|
это наборы: их называют форма, стор, разметка и сравнение черновиков, и написанное на месте
|
|
@@ -66,14 +74,21 @@ flowchart TD
|
|
|
66
74
|
домена, чей это набор, а общее нескольким приложениям — в общей либе. Одиночный адрес,
|
|
67
75
|
разделитель и знак-подпись перечислением не становятся: закрытого набора у них нет, и они
|
|
68
76
|
объявляются константой файла с говорящим именем.
|
|
77
|
+
<!-- rt-when: *.ts -->
|
|
78
|
+
|
|
69
79
|
- **Тип берётся из того пакета, где объявлен.** Своя копия чужого типа расходится с оригиналом
|
|
70
80
|
молча, а компилируется из них только одна.
|
|
81
|
+
<!-- rt-when: *.ts -->
|
|
82
|
+
|
|
71
83
|
- **Двухступенчатое приведение `as unknown as` запрещено правилом линтера.** Вместо него —
|
|
72
84
|
честный тип, сужение проверкой или чтение поля формой (`Reflect.get`); место, где иначе
|
|
73
85
|
нельзя, помечается точечным отключением с причиной в той же строке.
|
|
86
|
+
<!-- rt-when: *.ts -->
|
|
87
|
+
|
|
74
88
|
- **Отметка об устаревании ставится вместе с обходом потребителей.** Все правила
|
|
75
89
|
`eslint-plugin-sonarjs` подняты до отказа разом, и пометка на типе красит каждое место, где
|
|
76
90
|
его ещё зовут: один `@deprecated` на файл дал семнадцать замечаний в чужих доменах.
|
|
91
|
+
<!-- rt-when: *.ts -->
|
|
77
92
|
|
|
78
93
|
## Чего из закона здесь нет
|
|
79
94
|
|
|
@@ -40,9 +40,9 @@ description: Переносимый слой правил агента — за
|
|
|
40
40
|
|
|
41
41
|
## Порядок
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
Раскладка кладёт всё или ничего: отказ хотя бы по одному файлу не пишет ничего — половина
|
|
44
|
+
разложенного хуже целого. Правится либо надстройка здесь, либо сам ресурс — а это работа того
|
|
45
|
+
дерева, где пакет живёт исходниками, и здесь о ней не сказано ничего.
|
|
46
46
|
|
|
47
47
|
## Команды
|
|
48
48
|
|
|
@@ -56,13 +56,36 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
56
56
|
|
|
57
57
|
Строкой запуска слой правил не исчерпывается: часть его команд исполняет агент, а не программа.
|
|
58
58
|
`/feedback` кладёт слово о правилах блоком в файл предложений, `/skill-curator` разбирает
|
|
59
|
-
закрытую задачу, `/next-session` закрывает
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
закрытую задачу, `/next-session` закрывает заход.
|
|
60
|
+
|
|
61
|
+
Команд, которыми правят сам пакет, здесь нет: они зовутся там, где лежат его ресурсы, и вместе
|
|
62
|
+
с ними не едут.
|
|
63
|
+
|
|
64
|
+
## Что пакет везёт, а что остаётся дереву
|
|
65
|
+
|
|
66
|
+
Пакет ставят чужие деревья, и везёт он им только то, что они исполняют. Ресурс, у которого в
|
|
67
|
+
чужом дереве нет предмета или некому его позвать, ресурсом пакета не бывает — он живёт своим
|
|
68
|
+
ресурсом того дерева, где предмет есть.
|
|
69
|
+
|
|
70
|
+
Признак — не оценка, а два вопроса к ресурсу:
|
|
71
|
+
|
|
72
|
+
| Вопрос | «Нет» означает |
|
|
73
|
+
| ----------------------------------------------- | ---------------------------------------------- |
|
|
74
|
+
| Есть ли у потребителя то, о чём ресурс говорит? | предмета нет: заполнить компаньон нечем |
|
|
75
|
+
| Есть ли у потребителя кому его позвать? | исполнителя нет: команда у него не запускается |
|
|
76
|
+
|
|
77
|
+
Ответ «нет» хотя бы на один — ресурс остаётся дереву, которое пакет пишет.
|
|
78
|
+
|
|
79
|
+
**Перечень отменяемого границу не закрывает.** Строка в `skip` говорит «мне этого не надо» и
|
|
80
|
+
снимает раскладку у себя; ресурс при этом остаётся в пакете и продолжает ехать всем остальным.
|
|
81
|
+
Убирается он из самого пакета, а не из своей раскладки.
|
|
82
|
+
|
|
83
|
+
**Своё правило дерева объявляется наравне с пакетным:** та же форма, тот же закон сверху,
|
|
84
|
+
компаньон рядом и своя ветка в карте гейта. Читателю не должно быть видно, чем оно младше.
|
|
85
|
+
|
|
86
|
+
Что при этом должно быть верно, записано договорённостью в том дереве, которое пакет пишет:
|
|
87
|
+
там же живёт и проверка, которая границу держит. Чужому дереву судить ресурсы пакета нечего,
|
|
88
|
+
поэтому проверка сюда не едет.
|
|
66
89
|
|
|
67
90
|
## Обратная связь наверх
|
|
68
91
|
|
|
@@ -104,8 +127,8 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
104
127
|
сколько записей легло и сколько уже лежало. Строка «принято 0, уже лежало 3» означает, что
|
|
105
128
|
нового не уехало ничего.
|
|
106
129
|
|
|
107
|
-
|
|
108
|
-
|
|
130
|
+
Разбирают их там, где лежат правимые ресурсы и видно всех потребителей сразу, — а сюда
|
|
131
|
+
приезжает ответ приёма о том, сколько записей легло.
|
|
109
132
|
|
|
110
133
|
**Имя файла предложения в текстах дерева не называется.** Каталог предложений в историю не едет:
|
|
111
134
|
файл лежит на той машине, где его написали, и адрес на него ведёт в пустоту у всех остальных —
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# <О чём правило> — холодная часть
|
|
2
|
+
|
|
3
|
+
Ловушки: грабли, на которые уже наступали. Грузится не вместе с правилом, а по требованию —
|
|
4
|
+
при обычном решении она не нужна, она нужна тому, кто уже наступил.
|
|
5
|
+
|
|
6
|
+
Правило — `<имя-правила>`; статьи, которыми держится закон, стоят там.
|
|
7
|
+
|
|
8
|
+
## Ловушки
|
|
9
|
+
|
|
10
|
+
- **<Грабли, на которые уже наступали.>** <Чем это кончилось.>
|
package/assets/templates/rule.md
CHANGED
|
@@ -11,6 +11,9 @@ description: Правило под закон «<Название закона>
|
|
|
11
11
|
приёмом это делается. Чем это названо в этом дереве и где лежит — `implementation.md` рядом:
|
|
12
12
|
правило переносится между репозиториями, имена — нет.
|
|
13
13
|
|
|
14
|
+
**Холодная часть:** `pitfalls.md` рядом — <ловушки и поведение по разборам, если они у правила
|
|
15
|
+
есть>. Строка стоит только у правила, которое такой файл завело: у остального её нет вовсе.
|
|
16
|
+
|
|
14
17
|
## Как это называется здесь
|
|
15
18
|
|
|
16
19
|
<Таблица «в законе — здесь»: закон говорит без имён, дерево называет свои. Правка, по которой
|
|
@@ -56,6 +59,5 @@ flowchart TD
|
|
|
56
59
|
|
|
57
60
|
- `<имя-правила>-<что>` — <когда брать>.
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- **<Грабли, на которые уже наступали.>** <Чем это кончилось.>
|
|
62
|
+
Ловушек здесь нет: они живут в холодной части — `pitfalls.md` рядом, по образцу холодной
|
|
63
|
+
части. Правило кончается паттернами.
|
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;AA8S7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU9E"}
|
package/bin/agent-kit.js
CHANGED
|
@@ -14,9 +14,8 @@ import { unknownFlagsIn } from '../lib/argv.js';
|
|
|
14
14
|
import { readCatalog, resolveSelection } from '../lib/catalog.js';
|
|
15
15
|
import { adopt, doctor, init, list, stats, sync } from '../lib/commands.js';
|
|
16
16
|
import { CONFIG_PATH, readConfig } from '../lib/config.js';
|
|
17
|
-
import { FIX_FLAG, itemsOf, mark, POSTMORTEM_FLAG, PROPOSAL_FLAG, RELEASE_FLAG } from '../lib/cargo-state.js';
|
|
18
17
|
import { enroll, httpEnroll } from '../lib/enroll.js';
|
|
19
|
-
import {
|
|
18
|
+
import { httpShip } from '../lib/ship.js';
|
|
20
19
|
import { propose, treeSlugOf } from '../lib/shipment.js';
|
|
21
20
|
import { DEFAULT_DAYS } from '../lib/observations.js';
|
|
22
21
|
import { staleBuild } from '../lib/freshness.js';
|
|
@@ -40,13 +39,6 @@ const USAGE = [
|
|
|
40
39
|
' enroll --code <код> завести дерево по приглашению владельца: обмен кода на токен',
|
|
41
40
|
' enroll --token <токен> завести дерево токеном, выданным в админке приёма; в сеть не идёт',
|
|
42
41
|
' enroll --force перезаписать уже лежащий токен намеренно',
|
|
43
|
-
' mark --state <состояние> --postmortem <файл> --proposal <признак>',
|
|
44
|
-
' перевести свои записи груза в названное состояние',
|
|
45
|
-
' mark --fix <чем исправлено>',
|
|
46
|
-
' чем недочёт исправлен; обязателен при переходе в `fixed`, иначе не берётся',
|
|
47
|
-
' mark --release <версия выпуска>',
|
|
48
|
-
' в какой версии искать фикс; обязателен при переходе в `released`, иначе не берётся',
|
|
49
|
-
' mark --dry-run показать, что уехало бы, и ничего не отправлять',
|
|
50
42
|
'',
|
|
51
43
|
' --root <путь> корень проекта; по умолчанию текущий каталог',
|
|
52
44
|
'',
|
|
@@ -242,38 +234,6 @@ async function runPropose(env, argv) {
|
|
|
242
234
|
});
|
|
243
235
|
}
|
|
244
236
|
/** Приписка дерева к приёмнику по коду приглашения. */
|
|
245
|
-
/** Доводы отметки: незнакомый кончает команду — её действие уходит наружу и обратимо не всегда. */
|
|
246
|
-
const MARK_FLAGS = ['--state', POSTMORTEM_FLAG, PROPOSAL_FLAG, FIX_FLAG, RELEASE_FLAG, '--dry-run', '--root'];
|
|
247
|
-
/**
|
|
248
|
-
* Отметка состояния записей груза.
|
|
249
|
-
*
|
|
250
|
-
* Всё, что видно без сети, отбивается без сети: незнакомое состояние, вызов без записей и
|
|
251
|
-
* отсутствующий токен. Дерево при этом называется тем же признаком, что и у отправки груза, —
|
|
252
|
-
* приём сверит его с деревом токена.
|
|
253
|
-
*/
|
|
254
|
-
async function runMark(env, argv) {
|
|
255
|
-
const unknown = unknownFlagsIn(argv.slice(1), MARK_FLAGS);
|
|
256
|
-
if (unknown.length) {
|
|
257
|
-
return { code: 1, lines: [`таких доводов у \`mark\` нет: ${unknown.join(', ')}`] };
|
|
258
|
-
}
|
|
259
|
-
const config = readConfig(env.root);
|
|
260
|
-
if (!config) {
|
|
261
|
-
return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \`init\``] };
|
|
262
|
-
}
|
|
263
|
-
const state = optionOf(argv, '--state', '');
|
|
264
|
-
return mark({
|
|
265
|
-
state,
|
|
266
|
-
intake: config.intake,
|
|
267
|
-
tree: treeSlugOf(remoteOf(env.root), config.tree),
|
|
268
|
-
token: readToken(env.root, config.token),
|
|
269
|
-
items: itemsOf(argv, state, {
|
|
270
|
-
fixNote: optionOf(argv, FIX_FLAG, ''),
|
|
271
|
-
releaseVersion: optionOf(argv, RELEASE_FLAG, ''),
|
|
272
|
-
}),
|
|
273
|
-
dryRun: argv.includes('--dry-run'),
|
|
274
|
-
call: httpMark,
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
237
|
async function runEnroll(env, argv) {
|
|
278
238
|
const config = readConfig(env.root);
|
|
279
239
|
if (!config) {
|
|
@@ -298,7 +258,6 @@ const COMMANDS = {
|
|
|
298
258
|
stats: runStats,
|
|
299
259
|
propose: runPropose,
|
|
300
260
|
enroll: runEnroll,
|
|
301
|
-
mark: runMark,
|
|
302
261
|
doctor: (env) => doctor(env),
|
|
303
262
|
adopt: (env, argv) => adopt(env, argv.slice(1).filter((value) => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))),
|
|
304
263
|
};
|
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 { FIX_FLAG, itemsOf, mark, POSTMORTEM_FLAG, PROPOSAL_FLAG, RELEASE_FLAG } from '../lib/cargo-state.js';\nimport { enroll, httpEnroll } from '../lib/enroll.js';\nimport { httpMark, httpShip, readToken } 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 ' 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 ' mark --state <состояние> --postmortem <файл> --proposal <признак>',\n ' перевести свои записи груза в названное состояние',\n ' mark --fix <чем исправлено>',\n ' чем недочёт исправлен; обязателен при переходе в `fixed`, иначе не берётся',\n ' mark --release <версия выпуска>',\n ' в какой версии искать фикс; обязателен при переходе в `released`, иначе не берётся',\n ' mark --dry-run показать, что уехало бы, и ничего не отправлять',\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/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\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/** Приписка дерева к приёмнику по коду приглашения. */\n/** Доводы отметки: незнакомый кончает команду — её действие уходит наружу и обратимо не всегда. */\nconst MARK_FLAGS: readonly string[] = ['--state', POSTMORTEM_FLAG, PROPOSAL_FLAG, FIX_FLAG, RELEASE_FLAG, '--dry-run', '--root'];\n\n/**\n * Отметка состояния записей груза.\n *\n * Всё, что видно без сети, отбивается без сети: незнакомое состояние, вызов без записей и\n * отсутствующий токен. Дерево при этом называется тем же признаком, что и у отправки груза, —\n * приём сверит его с деревом токена.\n */\nasync function runMark(env: IEnvironment, argv: readonly string[]): Promise<IOutcomeOfCommand> {\n const unknown: readonly string[] = unknownFlagsIn(argv.slice(1), MARK_FLAGS);\n if (unknown.length) {\n return { code: 1, lines: [`таких доводов у \\`mark\\` нет: ${unknown.join(', ')}`] };\n }\n\n const config: IConfig | null = readConfig(env.root);\n if (!config) {\n return { code: 1, lines: [`настройки дерева нет: ${CONFIG_PATH}. Заведите её командой \\`init\\``] };\n }\n\n const state: string = optionOf(argv, '--state', '');\n\n return mark({\n state,\n intake: config.intake,\n tree: treeSlugOf(remoteOf(env.root), config.tree),\n token: readToken(env.root, config.token),\n items: itemsOf(argv, state, {\n fixNote: optionOf(argv, FIX_FLAG, ''),\n releaseVersion: optionOf(argv, RELEASE_FLAG, ''),\n }),\n dryRun: argv.includes('--dry-run'),\n call: httpMark,\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 stats: runStats,\n propose: runPropose,\n enroll: runEnroll,\n mark: runMark,\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 { 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 ' 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/** Сводка наблюдений: отрезок из флага, сегодняшний день — с края. */\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 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/assets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,eAAe,EAAe,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,eAAe,EAAe,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,OAAO,EAA0C,KAAK,EAAE,MAAM,aAAa,CAAC;AAErF,MAAM,WAAW,MAAM;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAUD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAU9H;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CASnF"}
|
package/lib/assets.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { chosenEntries } from './cascade.js';
|
|
10
10
|
import { readCatalog } from './catalog.js';
|
|
11
|
-
import { SKILL_FILE, SKILL_KINDS } from './config.js';
|
|
11
|
+
import { PITFALLS_FILE, SKILL_FILE, SKILL_KINDS } from './config.js';
|
|
12
12
|
/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */
|
|
13
13
|
const extensionOf = (id) => {
|
|
14
14
|
const dot = id.lastIndexOf('.');
|
|
@@ -23,6 +23,11 @@ const extensionOf = (id) => {
|
|
|
23
23
|
* дереве нет, а агенту, который правило читает, различать их незачем.
|
|
24
24
|
*/
|
|
25
25
|
export function targetOf(entry, layout) {
|
|
26
|
+
// Холодная часть ложится в каталог своего правила и под своим именем: правило читается как
|
|
27
|
+
// `<имя>/SKILL.md`, а её читают отдельно и по требованию — `<имя>/pitfalls.md`.
|
|
28
|
+
if (entry.kind === 'pitfalls') {
|
|
29
|
+
return join(layout[entry.kind], entry.name, PITFALLS_FILE);
|
|
30
|
+
}
|
|
26
31
|
return SKILL_KINDS.includes(entry.kind)
|
|
27
32
|
? join(layout[entry.kind], entry.name, SKILL_FILE)
|
|
28
33
|
: join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);
|
package/lib/assets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAW,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAW,aAAa,EAAE,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAerF,kFAAkF;AAClF,MAAM,WAAW,GAA2B,CAAC,EAAU,EAAU,EAAE;IAC/D,MAAM,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoD,EAAE,MAAuC;IAClH,2FAA2F;IAC3F,gFAAgF;IAChF,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,SAAiB;IAC5D,OAAO,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAU,EAAE,CAAC,CAAC;QAC1F,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC/B,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["/**\n * Что из везомого пакетом взял этот проект и куда оно ложится.\n *\n * Полный набор читает `catalog.ts`, здесь из него остаётся выбранное. Разделено потому, что\n * выбирать приходится раньше, чем раскладывать: `init` спрашивает, какие законы взять, а `list`\n * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.\n */\nimport { join } from 'node:path';\n\nimport { chosenEntries } from './cascade.js';\nimport { IEntryOfCatalog, readCatalog } from './catalog.js';\nimport { IConfig, PITFALLS_FILE, SKILL_FILE, SKILL_KINDS, TKind } from './config.js';\n\nexport interface IAsset {\n /** Идентификатор: `laws/application/money.md`. Он же путь надстройки и ключ в `only` и `skip`. */\n readonly id: string;\n readonly kind: TKind;\n /** Имя без рода, вида и расширения: `delivery`. У скила — имя каталога, которым его зовут. */\n readonly name: string;\n readonly text: string;\n /** Путь в дереве проекта, куда ресурс ложится. */\n readonly target: string;\n /** Запускается ли файл сам по себе: гарда без права на запуск не существует. */\n readonly executable: boolean;\n}\n\n/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */\nconst extensionOf: (id: string) => string = (id: string): string => {\n const dot: number = id.lastIndexOf('.');\n const slash: number = id.lastIndexOf('/');\n\n return dot > slash ? id.slice(dot) : '';\n};\n\n/**\n * Куда ложится ресурс. Скил читается агентом как `<имя>/SKILL.md`, и другого имени у него быть\n * не может: файл, названный по ресурсу, агент не найдёт вовсе. Остальные роды ложатся файлом —\n * по имени, а не по идентификатору: слой законов из идентификатора в путь переезжает, а вид\n * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом\n * дереве нет, а агенту, который правило читает, различать их незачем.\n */\nexport function targetOf(entry: Pick<IEntryOfCatalog, 'id' | 'kind' | 'name'>, layout: Readonly<Record<TKind, string>>): string {\n // Холодная часть ложится в каталог своего правила и под своим именем: правило читается как\n // `<имя>/SKILL.md`, а её читают отдельно и по требованию — `<имя>/pitfalls.md`.\n if (entry.kind === 'pitfalls') {\n return join(layout[entry.kind], entry.name, PITFALLS_FILE);\n }\n\n return SKILL_KINDS.includes(entry.kind)\n ? join(layout[entry.kind], entry.name, SKILL_FILE)\n : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);\n}\n\nexport function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[] {\n return chosenEntries(readCatalog(assetsDir), config).map((entry: IEntryOfCatalog): IAsset => ({\n id: entry.id,\n kind: entry.kind,\n name: entry.name,\n text: entry.text,\n target: targetOf(entry, config.layout),\n executable: entry.executable,\n }));\n}\n"]}
|
package/lib/cascade.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cascade.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,eAAe,EAAY,UAAU,EAAE,MAAM,cAAc,CAAC;AAIpF,qDAAqD;AACrD,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"cascade.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAiB,eAAe,EAAY,UAAU,EAAE,MAAM,cAAc,CAAC;AAIpF,qDAAqD;AACrD,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AA0FD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,WAAW,EAAE,CAM9G;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,WAAW,EAAE,CAE9G;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,eAAe,EAAE,CAIpH;AAED,gDAAgD;AAChD,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACvB;AA0BD,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,SAAS,EAAE,CAqB1G"}
|
package/lib/cascade.js
CHANGED
|
@@ -49,6 +49,24 @@ function patternsCutByRules(catalog, selection, rootByRule) {
|
|
|
49
49
|
}
|
|
50
50
|
return cuts;
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Холодные части, снятые вслед за своим правилом. Родитель ищется по имени, а не по полю шапки:
|
|
54
|
+
* холодная часть принадлежит одному правилу и называется так же, как оно, — второго имени у неё
|
|
55
|
+
* нет и быть не может.
|
|
56
|
+
*/
|
|
57
|
+
function pitfallsCutByRules(catalog, selection, rootByRule) {
|
|
58
|
+
const taken = takenNames(catalog, selection, 'rules');
|
|
59
|
+
const known = knownNames(catalog, 'rules');
|
|
60
|
+
const cuts = [];
|
|
61
|
+
for (const entry of chosenOfKind(catalog, selection, 'pitfalls')) {
|
|
62
|
+
const rule = shortNameOf(entry);
|
|
63
|
+
const standing = taken.has(rule) && !rootByRule.has(rule);
|
|
64
|
+
if (known.has(rule) && !standing) {
|
|
65
|
+
cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return cuts;
|
|
69
|
+
}
|
|
52
70
|
/**
|
|
53
71
|
* Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.
|
|
54
72
|
*
|
|
@@ -64,7 +82,7 @@ export function cascadeCuts(catalog, selection) {
|
|
|
64
82
|
/** Правило, снятое законом: для паттернов при нём корнем цепочки будет этот закон. */
|
|
65
83
|
const rootByRule = new Map();
|
|
66
84
|
const rules = rulesCutByLaws(catalog, selection, rootByRule);
|
|
67
|
-
return [...rules, ...patternsCutByRules(catalog, selection, rootByRule)];
|
|
85
|
+
return [...rules, ...patternsCutByRules(catalog, selection, rootByRule), ...pitfallsCutByRules(catalog, selection, rootByRule)];
|
|
68
86
|
}
|
|
69
87
|
/**
|
|
70
88
|
* Ресурсы, названные выбором поимённо и всё равно снятые каскадом.
|
package/lib/cascade.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cascade.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Каскад отказа: ресурс, чей родитель не поехал в дерево, снимается вслед за ним.\n *\n * Отдельным модулем от каталога: каталог знает, какие ресурсы бывают, а каскад — как они связаны\n * родством. Связь родителя с потомком читают двое — сверка связности пакета и сама раскладка, —\n * и оба берут её отсюда.\n */\n\nimport { frontMatterOf, IEntryOfCatalog, isChosen, ISelection } from './catalog.js';\nimport { TKind } from './config.js';\nimport { matchesVariant } from './variants.js';\n\n/** Ресурс, снятый вслед за отвергнутым родителем. */\nexport interface ICascadeCut {\n readonly id: string;\n /** Ближайший родитель: у правила — его закон, у паттерна — его правило. */\n readonly parent: string;\n /**\n * Отвергнутый корень цепочки — то, что дерево действительно отвергло или не выбрало.\n * Ближайшего родителя мало: паттерн уходит вслед за правилом, которого в отказе нет, и\n * искать его там читатель пойдёт зря.\n */\n readonly root: string;\n}\n\n/** Последнее звено имени: `application/money` → `money`. Им ресурсы и ссылаются друг на друга. */\nconst shortNameOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => entry.name.split('/').pop() ?? entry.name;\n\n/** Взятые ресурсы одного рода. */\nfunction chosenOfKind(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): readonly IEntryOfCatalog[] {\n return catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind && isChosen(entry, selection));\n}\n\n/** Короткие имена взятых ресурсов рода. */\nfunction takenNames(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): ReadonlySet<string> {\n return new Set(chosenOfKind(catalog, selection, kind).map(shortNameOf));\n}\n\n/** Короткие имена всех ресурсов рода, взяты они или нет. */\nfunction knownNames(catalog: readonly IEntryOfCatalog[], kind: TKind): ReadonlySet<string> {\n return new Set(catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind).map(shortNameOf));\n}\n\n/** Правила, снятые вслед за своим законом. Заодно называет корень цепочки для паттернов при них. */\nfunction rulesCutByLaws(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: Map<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'laws');\n const known: ReadonlySet<string> = knownNames(catalog, 'laws');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'rules')) {\n const law: string = frontMatterOf(entry.text).law;\n\n if (law && known.has(law) && !taken.has(law)) {\n cuts.push({ id: entry.id, parent: law, root: law });\n rootByRule.set(shortNameOf(entry), law);\n }\n }\n\n return cuts;\n}\n\n/** Паттерны, снятые вслед за своим правилом: либо оно не взято, либо само ушло за своим законом. */\nfunction patternsCutByRules(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: ReadonlyMap<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'rules');\n const known: ReadonlySet<string> = knownNames(catalog, 'rules');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'patterns')) {\n const rule: string = frontMatterOf(entry.text).rule;\n const standing: boolean = taken.has(rule) && !rootByRule.has(rule);\n\n if (rule && known.has(rule) && !standing) {\n cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });\n }\n }\n\n return cuts;\n}\n\n/**\n * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.\n *\n * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с\n * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по\n * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями\n * переписывал бы шапки всех правил при нём.\n *\n * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит\n * сверка связности пакета, до всякой раскладки в дереве.\n */\nexport function cascadeCuts(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n /** Правило, снятое законом: для паттернов при нём корнем цепочки будет этот закон. */\n const rootByRule: Map<string, string> = new Map<string, string>();\n const rules: readonly ICascadeCut[] = rulesCutByLaws(catalog, selection, rootByRule);\n\n return [...rules, ...patternsCutByRules(catalog, selection, rootByRule)];\n}\n\n/**\n * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.\n *\n * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое\n * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,\n * кто ничего не просил, здесь — тот, кто попросил прямо.\n */\nexport function namedButCut(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n return cascadeCuts(catalog, selection).filter((one: ICascadeCut): boolean => selection.only.includes(one.id));\n}\n\n/**\n * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.\n *\n * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —\n * один ресурс: связь родителя с потомком по одной записи не видна.\n */\nexport function chosenEntries(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IEntryOfCatalog[] {\n const cut: ReadonlySet<string> = new Set(cascadeCuts(catalog, selection).map((one: ICascadeCut): string => one.id));\n\n return catalog.filter((entry: IEntryOfCatalog): boolean => isChosen(entry, selection) && !cut.has(entry.id));\n}\n\n/** Строка отказа, которая ничего не снимает. */\nexport interface IIdleSkip {\n readonly id: string;\n /** Чем названное ею уже снято: имя отвергнутого родителя, либо пусто — такого ресурса нет. */\n readonly by: string;\n}\n\n/**\n * Строки отказа, которые ничего не снимают: названное ими снято каскадом или в каталоге не\n * значится вовсе.\n *\n * Не отказ, а предупреждение: настройка, верная до обновления пакета, становится лишней сама,\n * без единой правки в дереве, и отбивать за это раскладку значило бы наказывать за вчерашнюю\n * правоту.\n *\n * Строка на ресурс чужого вида лишней не считается никогда: ею дерево гасит отказ о ресурсе,\n * у которого нет подходящего вида, — то есть работу она делает.\n */\n/**\n * Корень цепочки, которой ресурс снят и без этой строки отказа. Пусто — каскад его не трогает.\n *\n * Каскад считается от отбора без самой строки: иначе снятое ею читалось бы как снятое родителем,\n * и лишней оказалась бы любая строка отказа подряд.\n */\nfunction cutParentOf(catalog: readonly IEntryOfCatalog[], selection: ISelection, id: string): string | null {\n const without: ISelection = { ...selection, skip: selection.skip.filter((one: string): boolean => one !== id) };\n const cut: ICascadeCut | undefined = cascadeCuts(catalog, without).find((one: ICascadeCut): boolean => one.id === id);\n\n return cut ? cut.root : null;\n}\n\nexport function idleSkips(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IIdleSkip[] {\n const idle: IIdleSkip[] = [];\n\n for (const id of selection.skip) {\n const entry: IEntryOfCatalog | undefined = catalog.find((one: IEntryOfCatalog): boolean => one.id === id);\n\n if (!entry) {\n idle.push({ id, by: '' });\n } else if (matchesVariant(entry.variant, selection.variants)) {\n const by: string | null = cutParentOf(catalog, selection, id);\n\n if (by !== null) {\n idle.push({ id, by });\n }\n } else {\n // Строка на ресурс чужого вида работу делает: ею дерево гасит отказ о ресурсе, у\n // которого подходящего вида нет\n }\n }\n\n return idle;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cascade.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cascade.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Каскад отказа: ресурс, чей родитель не поехал в дерево, снимается вслед за ним.\n *\n * Отдельным модулем от каталога: каталог знает, какие ресурсы бывают, а каскад — как они связаны\n * родством. Связь родителя с потомком читают двое — сверка связности пакета и сама раскладка, —\n * и оба берут её отсюда.\n */\n\nimport { frontMatterOf, IEntryOfCatalog, isChosen, ISelection } from './catalog.js';\nimport { TKind } from './config.js';\nimport { matchesVariant } from './variants.js';\n\n/** Ресурс, снятый вслед за отвергнутым родителем. */\nexport interface ICascadeCut {\n readonly id: string;\n /** Ближайший родитель: у правила — его закон, у паттерна — его правило. */\n readonly parent: string;\n /**\n * Отвергнутый корень цепочки — то, что дерево действительно отвергло или не выбрало.\n * Ближайшего родителя мало: паттерн уходит вслед за правилом, которого в отказе нет, и\n * искать его там читатель пойдёт зря.\n */\n readonly root: string;\n}\n\n/** Последнее звено имени: `application/money` → `money`. Им ресурсы и ссылаются друг на друга. */\nconst shortNameOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => entry.name.split('/').pop() ?? entry.name;\n\n/** Взятые ресурсы одного рода. */\nfunction chosenOfKind(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): readonly IEntryOfCatalog[] {\n return catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind && isChosen(entry, selection));\n}\n\n/** Короткие имена взятых ресурсов рода. */\nfunction takenNames(catalog: readonly IEntryOfCatalog[], selection: ISelection, kind: TKind): ReadonlySet<string> {\n return new Set(chosenOfKind(catalog, selection, kind).map(shortNameOf));\n}\n\n/** Короткие имена всех ресурсов рода, взяты они или нет. */\nfunction knownNames(catalog: readonly IEntryOfCatalog[], kind: TKind): ReadonlySet<string> {\n return new Set(catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind).map(shortNameOf));\n}\n\n/** Правила, снятые вслед за своим законом. Заодно называет корень цепочки для паттернов при них. */\nfunction rulesCutByLaws(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: Map<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'laws');\n const known: ReadonlySet<string> = knownNames(catalog, 'laws');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'rules')) {\n const law: string = frontMatterOf(entry.text).law;\n\n if (law && known.has(law) && !taken.has(law)) {\n cuts.push({ id: entry.id, parent: law, root: law });\n rootByRule.set(shortNameOf(entry), law);\n }\n }\n\n return cuts;\n}\n\n/** Паттерны, снятые вслед за своим правилом: либо оно не взято, либо само ушло за своим законом. */\nfunction patternsCutByRules(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: ReadonlyMap<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'rules');\n const known: ReadonlySet<string> = knownNames(catalog, 'rules');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'patterns')) {\n const rule: string = frontMatterOf(entry.text).rule;\n const standing: boolean = taken.has(rule) && !rootByRule.has(rule);\n\n if (rule && known.has(rule) && !standing) {\n cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });\n }\n }\n\n return cuts;\n}\n\n/**\n * Холодные части, снятые вслед за своим правилом. Родитель ищется по имени, а не по полю шапки:\n * холодная часть принадлежит одному правилу и называется так же, как оно, — второго имени у неё\n * нет и быть не может.\n */\nfunction pitfallsCutByRules(\n catalog: readonly IEntryOfCatalog[],\n selection: ISelection,\n rootByRule: ReadonlyMap<string, string>\n): readonly ICascadeCut[] {\n const taken: ReadonlySet<string> = takenNames(catalog, selection, 'rules');\n const known: ReadonlySet<string> = knownNames(catalog, 'rules');\n const cuts: ICascadeCut[] = [];\n\n for (const entry of chosenOfKind(catalog, selection, 'pitfalls')) {\n const rule: string = shortNameOf(entry);\n const standing: boolean = taken.has(rule) && !rootByRule.has(rule);\n\n if (known.has(rule) && !standing) {\n cuts.push({ id: entry.id, parent: rule, root: rootByRule.get(rule) ?? rule });\n }\n }\n\n return cuts;\n}\n\n/**\n * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.\n *\n * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с\n * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по\n * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями\n * переписывал бы шапки всех правил при нём.\n *\n * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит\n * сверка связности пакета, до всякой раскладки в дереве.\n */\nexport function cascadeCuts(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n /** Правило, снятое законом: для паттернов при нём корнем цепочки будет этот закон. */\n const rootByRule: Map<string, string> = new Map<string, string>();\n const rules: readonly ICascadeCut[] = rulesCutByLaws(catalog, selection, rootByRule);\n\n return [...rules, ...patternsCutByRules(catalog, selection, rootByRule), ...pitfallsCutByRules(catalog, selection, rootByRule)];\n}\n\n/**\n * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.\n *\n * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое\n * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,\n * кто ничего не просил, здесь — тот, кто попросил прямо.\n */\nexport function namedButCut(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[] {\n return cascadeCuts(catalog, selection).filter((one: ICascadeCut): boolean => selection.only.includes(one.id));\n}\n\n/**\n * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.\n *\n * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —\n * один ресурс: связь родителя с потомком по одной записи не видна.\n */\nexport function chosenEntries(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IEntryOfCatalog[] {\n const cut: ReadonlySet<string> = new Set(cascadeCuts(catalog, selection).map((one: ICascadeCut): string => one.id));\n\n return catalog.filter((entry: IEntryOfCatalog): boolean => isChosen(entry, selection) && !cut.has(entry.id));\n}\n\n/** Строка отказа, которая ничего не снимает. */\nexport interface IIdleSkip {\n readonly id: string;\n /** Чем названное ею уже снято: имя отвергнутого родителя, либо пусто — такого ресурса нет. */\n readonly by: string;\n}\n\n/**\n * Строки отказа, которые ничего не снимают: названное ими снято каскадом или в каталоге не\n * значится вовсе.\n *\n * Не отказ, а предупреждение: настройка, верная до обновления пакета, становится лишней сама,\n * без единой правки в дереве, и отбивать за это раскладку значило бы наказывать за вчерашнюю\n * правоту.\n *\n * Строка на ресурс чужого вида лишней не считается никогда: ею дерево гасит отказ о ресурсе,\n * у которого нет подходящего вида, — то есть работу она делает.\n */\n/**\n * Корень цепочки, которой ресурс снят и без этой строки отказа. Пусто — каскад его не трогает.\n *\n * Каскад считается от отбора без самой строки: иначе снятое ею читалось бы как снятое родителем,\n * и лишней оказалась бы любая строка отказа подряд.\n */\nfunction cutParentOf(catalog: readonly IEntryOfCatalog[], selection: ISelection, id: string): string | null {\n const without: ISelection = { ...selection, skip: selection.skip.filter((one: string): boolean => one !== id) };\n const cut: ICascadeCut | undefined = cascadeCuts(catalog, without).find((one: ICascadeCut): boolean => one.id === id);\n\n return cut ? cut.root : null;\n}\n\nexport function idleSkips(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IIdleSkip[] {\n const idle: IIdleSkip[] = [];\n\n for (const id of selection.skip) {\n const entry: IEntryOfCatalog | undefined = catalog.find((one: IEntryOfCatalog): boolean => one.id === id);\n\n if (!entry) {\n idle.push({ id, by: '' });\n } else if (matchesVariant(entry.variant, selection.variants)) {\n const by: string | null = cutParentOf(catalog, selection, id);\n\n if (by !== null) {\n idle.push({ id, by });\n }\n } else {\n // Строка на ресурс чужого вида работу делает: ею дерево гасит отказ о ресурсе, у\n // которого подходящего вида нет\n }\n }\n\n return idle;\n}\n"]}
|
package/lib/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAsB7C,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACvC;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAsB7C,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACvC;AA2DD,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,MAAyB,CAAC;AA+UpD;;;;GAIG;AACH,wBAAgB,IAAI,CAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,SAAS,MAAM,EAAO,EAC5B,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAC/C,SAAS,GAAE,MAAW,GACvB,iBAAiB,CAgCnB;AA8FD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA4DzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CA+CpF;AAQD,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CAC1B;AAqHD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,iBAAiB,CAuDlF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2E3D;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2DzD"}
|