@rt-tools/agent-kit 0.8.0 → 0.8.2

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.
Files changed (104) hide show
  1. package/README.md +24 -19
  2. package/assets/agents/qa-engineer.md +1 -1
  3. package/assets/checks/board.github.mjs +56 -17
  4. package/assets/checks/check-board.github.mjs +49 -5
  5. package/assets/checks/check-reuse.mjs +9 -7
  6. package/assets/checks/task-new.github.mjs +33 -5
  7. package/assets/commands/agent-kit-digest.md +10 -5
  8. package/assets/commands/next-session.md +4 -4
  9. package/assets/commands/skill-curator.md +11 -9
  10. package/assets/defaults/gate-map.sh +11 -4
  11. package/assets/defaults/project.sh +46 -0
  12. package/assets/docs/GLOSSARY.md +28 -26
  13. package/assets/hooks/docs-guard.sh +19 -3
  14. package/assets/hooks/git-guard-delivery.sh +106 -13
  15. package/assets/hooks/proposal-guard.sh +93 -0
  16. package/assets/hooks/reuse-first-guard.sh +68 -14
  17. package/assets/hooks/skill-gate-layers.sh +1 -1
  18. package/assets/hooks/skill-gate.sh +26 -0
  19. package/assets/hooks/task-flow-guard.sh +44 -18
  20. package/assets/hooks/window-fill-guard.sh +1 -1
  21. package/assets/laws/delivery.md +13 -7
  22. package/assets/laws/project-documentation.md +21 -0
  23. package/assets/laws/verifiability.md +6 -1
  24. package/assets/laws/work-conduct.md +67 -3
  25. package/assets/patterns/git-workflow-commit.azure.md +10 -2
  26. package/assets/patterns/git-workflow-commit.github.md +15 -2
  27. package/assets/patterns/git-workflow-commit.gitlab.md +10 -2
  28. package/assets/patterns/git-workflow-merge.md +1 -1
  29. package/assets/patterns/reuse-first-extend.md +12 -3
  30. package/assets/patterns/spec-driven-domain.md +7 -1
  31. package/assets/patterns/spec-driven-rule.md +6 -0
  32. package/assets/patterns/task-flow-close.md +78 -9
  33. package/assets/patterns/task-flow-handoff.md +27 -4
  34. package/assets/patterns/task-flow-resume.md +23 -5
  35. package/assets/patterns/task-flow-start.md +5 -1
  36. package/assets/rules/browser-verification.md +10 -1
  37. package/assets/rules/doc-style.md +13 -5
  38. package/assets/rules/git-workflow.azure.md +12 -7
  39. package/assets/rules/git-workflow.github.md +31 -13
  40. package/assets/rules/git-workflow.gitlab.md +12 -7
  41. package/assets/rules/reuse-first.md +1 -1
  42. package/assets/rules/spec-driven.md +4 -0
  43. package/assets/rules/task-flow.md +47 -22
  44. package/assets/rules/testing.md +19 -0
  45. package/assets/rules/typescript-conventions.md +12 -0
  46. package/assets/skills/agent-kit-extend.md +173 -0
  47. package/assets/skills/agent-kit.md +62 -10
  48. package/assets/traits.json +14 -0
  49. package/bin/agent-kit.d.ts.map +1 -1
  50. package/bin/agent-kit.js +31 -16
  51. package/bin/agent-kit.js.map +1 -1
  52. package/index.d.ts +1 -0
  53. package/index.d.ts.map +1 -1
  54. package/index.js +1 -0
  55. package/index.js.map +1 -1
  56. package/lib/argv.d.ts +17 -0
  57. package/lib/argv.d.ts.map +1 -0
  58. package/lib/argv.js +44 -0
  59. package/lib/argv.js.map +1 -0
  60. package/lib/cargo.d.ts +88 -0
  61. package/lib/cargo.d.ts.map +1 -0
  62. package/lib/cargo.js +16 -0
  63. package/lib/cargo.js.map +1 -0
  64. package/lib/catalog.d.ts +18 -1
  65. package/lib/catalog.d.ts.map +1 -1
  66. package/lib/catalog.js +12 -2
  67. package/lib/catalog.js.map +1 -1
  68. package/lib/commands.d.ts +0 -26
  69. package/lib/commands.d.ts.map +1 -1
  70. package/lib/commands.js +78 -122
  71. package/lib/commands.js.map +1 -1
  72. package/lib/companion.d.ts +37 -0
  73. package/lib/companion.d.ts.map +1 -1
  74. package/lib/companion.js +42 -1
  75. package/lib/companion.js.map +1 -1
  76. package/lib/config.d.ts +28 -0
  77. package/lib/config.d.ts.map +1 -1
  78. package/lib/config.js +20 -0
  79. package/lib/config.js.map +1 -1
  80. package/lib/ship.d.ts +39 -0
  81. package/lib/ship.d.ts.map +1 -0
  82. package/lib/ship.js +87 -0
  83. package/lib/ship.js.map +1 -0
  84. package/lib/shipment.d.ts +60 -0
  85. package/lib/shipment.d.ts.map +1 -0
  86. package/lib/shipment.js +247 -0
  87. package/lib/shipment.js.map +1 -0
  88. package/lib/snapshot.d.ts +30 -0
  89. package/lib/snapshot.d.ts.map +1 -0
  90. package/lib/snapshot.js +73 -0
  91. package/lib/snapshot.js.map +1 -0
  92. package/lib/traits.d.ts +32 -0
  93. package/lib/traits.d.ts.map +1 -0
  94. package/lib/traits.js +82 -0
  95. package/lib/traits.js.map +1 -0
  96. package/package.json +6 -2
  97. package/rt-tools-agent-kit-0.8.2.tgz +0 -0
  98. package/lib/submit.d.ts +0 -24
  99. package/lib/submit.d.ts.map +0 -1
  100. package/lib/submit.js +0 -26
  101. package/lib/submit.js.map +0 -1
  102. package/rt-tools-agent-kit-0.8.0.tgz +0 -0
  103. /package/assets/rules/{entity-conventions.md → entity-conventions.needs-admin.md} +0 -0
  104. /package/assets/rules/{observability.md → observability.needs-app.md} +0 -0
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: agent-kit-extend
3
+ description: Готовые примеры того, как дерево дописывает своё поверх пакета правил — надстройка над разложенным текстом, своя ветка карты гейта, своя функция профиля, свой признак единообразия, свой закон и правило. Брать, когда пакетный текст говорит не то, что верно здесь, гейт требует не то правило, гард судит не по тем путям, или своё поведение надо дописать, не трогая пакет. Где что настраивается и как устроена раскладка — скил agent-kit; форма нового скила — write-a-skill.
4
+ ---
5
+
6
+ # Как дописать своё поверх пакета
7
+
8
+ Скил `agent-kit` называет, **где** настраивается каждый род правки. Здесь — **как** выглядит
9
+ сама правка, на готовых примерах, и чем каждая проверяется.
10
+
11
+ Одно правило общее для всех пяти: разложенный файл не правится на месте. Он несёт шапку
12
+ `rt-kit v… · <ресурс> · <сумма>`, правка в нём теряется на следующей раскладке и до тех пор
13
+ выглядит применённой, а `sync` на такой файл отказывает вместо того, чтобы переписать молча.
14
+
15
+ ## Когда брать
16
+
17
+ - Пакетный текст говорит не то, что верно здесь: имена, пути, приёмы этого дерева.
18
+ - Гейт требует под файл не то правило — или молчит там, где правило есть.
19
+ - Гард судит не по тем путям: чужие корни, свой набор проверок, своя форма ветки.
20
+ - Заводится своё — признак единообразия, проверка, закон с правилом, — чего пакет не везёт.
21
+
22
+ ## Текст: надстройка сливается по разделам
23
+
24
+ Файл кладётся в `overrides/<идентификатор ресурса>` — путь повторяет ресурс один в один:
25
+ `rules/testing.md` надстраивается файлом `rules/testing.md`.
26
+
27
+ ```markdown
28
+ ## Ловушки этого дерева
29
+
30
+ - **Снимок дерева правится тем же коммитом, что и объявление.** Иначе установка у соседа
31
+ ставит не то, что стоит здесь.
32
+ ```
33
+
34
+ | Заголовок в надстройке | Что происходит |
35
+ | ---------------------- | ------------------------- |
36
+ | есть у пакета | раздел замещается целиком |
37
+ | нет у пакета | дописывается в конец |
38
+ | есть, но тело пустое | раздел пакета снимается |
39
+
40
+ **Замещение — целиком, и это главная ловушка.** Свой пункт, дописанный под пакетным заголовком
41
+ `## Ловушки`, уносит все пакетные пункты этого раздела разом, и пропажу не видно ничем: файл
42
+ выглядит собранным. Поэтому заголовок в примере выше свой. Пакетный заголовок берут только
43
+ тогда, когда пакетный текст здесь неверен и его правда надо снять.
44
+
45
+ **Заголовок, стоящий внутри примера, разделом не является.** Разбор пропускает всё, что лежит
46
+ в ограде блока кода: образец документа с собственными заголовками рвал бы ресурс на куски.
47
+ Поэтому надстройка, названная таким заголовком, не замещает ничего — она попадает в строку «нет
48
+ у пакета» и дописывается новым разделом в конец. Правка при этом выглядит сработавшей: файл
49
+ собран, `sync --check` зелёный, а нужный абзац остался прежним.
50
+
51
+ Дотягиваются до него заголовком того раздела, внутри которого он лежит, — и замещают этот
52
+ раздел целиком, вместе с примером:
53
+
54
+ ````bash
55
+ # какие заголовки у ресурса на самом деле — примеры в ограде сюда не попадают
56
+ awk '/^```/ { fence = !fence } !fence && /^## / { print }' <файл ресурса>
57
+ ````
58
+
59
+ Проверяется раскладкой: `sync`, затем `sync --check` — и глазами по разложенному файлу, на
60
+ месте ли пакетные разделы.
61
+
62
+ От ресурса целиком отказываются не здесь, а списком `skip` в конфиге: надстройка правит текст,
63
+ `skip` отменяет файл.
64
+
65
+ ## Гейт: своя ветка решает раньше умолчания
66
+
67
+ Гейт спрашивает `skill_for` — она печатает имя правила или молчит. Молчание значит «правила на
68
+ это нет», и правка проходит.
69
+
70
+ ```bash
71
+ skill_for() {
72
+ kind="$1"; target="$2"; written="$3"
73
+
74
+ case "$kind" in
75
+ edit)
76
+ case "$target" in
77
+ # Частное — всегда раньше общего: файл истории не файл компонента.
78
+ *.stories.ts) printf '%s\n' 'showcase'; return 0 ;;
79
+ esac
80
+ ;;
81
+ esac
82
+
83
+ # Всё остальное разбирает умолчание пакета — иначе оно теряется целиком.
84
+ command -v skill_for_default >/dev/null 2>&1 && skill_for_default "$kind" "$target" "$written"
85
+
86
+ return 0
87
+ }
88
+ ```
89
+
90
+ Две вещи здесь обязательны. **Порядок веток:** первое совпадение выигрывает, и общая ветка,
91
+ поставленная выше частной, съедает её молча. **Вызов умолчания:** объявив функцию заново и не
92
+ позвав `_default`, дерево остаётся без всех пакетных веток сразу — а выглядит это как «гейт
93
+ перестал требовать правила».
94
+
95
+ Проверяется сценариями гейта из набора пакета: они гоняют карту, ничего не раскладывая.
96
+
97
+ ## Гард: профиль отвечает за имена и команды
98
+
99
+ Тем же приёмом объявляются функции профиля — что гонять перед пушем, какой документ едет парой,
100
+ чем линтуется файл, что здесь считается кодом приложения, какая форма ветки законна.
101
+
102
+ ```bash
103
+ # Какой документ обязан ехать тем же коммитом. Печатает образец пути или молчит.
104
+ rt_docs_pair_for() {
105
+ case "$1" in
106
+ *.spec.ts) return 0 ;;
107
+ libs/kit/src/*/*.component.ts) printf '%s' "${1%/*}/CONTEXT\.md" ;;
108
+ esac
109
+ }
110
+ ```
111
+
112
+ Печатается **образец**, а не путь: гард сверяет им состав коммита. Умолчание зовётся так же —
113
+ `rt_docs_pair_for_default "$@"` — везде, где своё правило случай не закрыло.
114
+
115
+ Путь приходит от корня дерева. Признак по подстроке вида `*/projects/*` совпадает и с чужим
116
+ каталогом за пределами репозитория — так запись в домашний каталог была отбита требованием
117
+ замысла, к ней не относящимся.
118
+
119
+ ## Признаки и проверки: данные, а не код
120
+
121
+ Признак единообразия — данные. Дерево называет наборы пакета, чьё готовое оно берёт, и
122
+ дописывает свои файлом; совпавший ключ замещает пакетный.
123
+
124
+ ```json
125
+ {
126
+ "sourceRoots": ["apps", "libs"],
127
+ "reuse": { "bundles": ["kit"], "signals": "tools/signals/own.json" }
128
+ }
129
+ ```
130
+
131
+ Объект сливается ключ за ключом: назвав один ключ раздела, дерево не теряет соседних. **Список
132
+ — наоборот, замещается целиком**, и это ловушка: назвав `sourceRoots`, дерево получает ровно
133
+ названное, а не пакетные корни плюс свои. «Дописать в список» и «убрать из списка» в этой записи
134
+ неразличимы, поэтому список всегда пишется полностью.
135
+
136
+ Набор объявляется по тому, что дерево **потребляет**. Дерево, в котором кит написан, а не
137
+ позван, объявив его набор, получит советы звать кит на файлах самого кита: признак верен, но
138
+ обращён не туда.
139
+
140
+ ## Свой закон и правило
141
+
142
+ Пакет везёт слой правил, но не запрещает свой. Закон дерева ложится рядом с пакетными, правило
143
+ под него — среди скилов, и связь идёт через шапку: у правила `law:` с именем закона, у паттерна
144
+ `rule:` с именем правила. Имя, которому ничего не отвечает, отбивает сверку связности.
145
+
146
+ Утверждение правила получает строку в спутнике `implementation.md` — привязку к файлу и символу.
147
+ Утверждение, которому места в коде не нашлось, в проверяемый раздел не ставится: ему место в
148
+ «Ловушках» прозой.
149
+
150
+ Проверяется сверкой спеков — до пуша.
151
+
152
+ ## Частые промахи
153
+
154
+ - **Правка на месте вместо надстройки.** Разложенный файл узнаётся по шапке, а не по каталогу:
155
+ раскладка ложится в те же `tools/` и `.claude/`, где лежит своё.
156
+ - **Свой пункт дописан к пакетному заголовку** — пакетные пункты этого раздела ушли молча.
157
+ - **Надстройка названа заголовком, который стоит в примере.** Заместить она ничего не может —
158
+ такого раздела у ресурса нет, — и уезжает новым разделом в конец. Видно это глазами по
159
+ разложенному файлу: два одинаковых заголовка, один в ограде примера, другой последним
160
+ разделом; раскладка при этом зелёная, потому что расхождения с пакетом нет.
161
+ - **Функция объявлена заново без вызова `_default`** — вместе со своим случаем потеряны все
162
+ пакетные.
163
+ - **Общая ветка карты стоит выше частной** — частная не выполняется никогда.
164
+ - **Замена по шаблону в файле оболочки** — `case` теряет свою `esac`, и гард с ошибкой синтаксиса
165
+ отвечает ненулевым кодом, то есть «правка отбита». После правки — `bash -n`.
166
+ - **Правка ресурса пакета без сборки.** Строка запуска читает собранное, а не исходники:
167
+ порядок всегда один — правка, сборка, `sync`.
168
+ - **Форматтер правит ресурс на коммите, и раскладка отстаёт задним числом.** Разложенное
169
+ сходилось в ту минуту, когда его раскладывали, а ресурс изменился после: пример с оградой
170
+ внутри примера форматтер переписывает на ограду длиннее, сумма ресурса меняется, и
171
+ `sync --check` краснеет уже на следующем шаге. Порядок обхода: прогнать форматтер на
172
+ правленом ресурсе, потом `sync`, потом коммит — либо переразложить и добавить в тот же
173
+ коммит.
@@ -27,12 +27,16 @@ description: Переносимый слой правил агента — за
27
27
  | какие признаки единообразия дерево берёт | `checks.json`, ключи `reuse.bundles` и `reuse.signals` |
28
28
  | раздел разложенного текста | `.claude/rt-kit/overrides/<идентификатор ресурса>` |
29
29
  | что брать, а от чего отказаться | `.claude/rt-kit.json`, ключи `only` и `skip` |
30
+ | что у дерева есть: хранилище, админка, пакеты | `.claude/rt-kit.json`, ключ `has` |
30
31
  | сам механизм — гард, проверка, текст правила | ресурс в пакете |
31
32
 
32
33
  Надстройка объявляет функцию заново и вправе позвать умолчание тем же именем с суффиксом
33
34
  `_default`. Слияние текста идёт по разделам `## `: совпавший заголовок замещает, новый
34
35
  дописывается, пустой снимает раздел пакета.
35
36
 
37
+ Готовый пример на каждую строку этой таблицы — скил `agent-kit-extend`: как выглядит сама
38
+ правка, чем она проверяется и чем кончается, если положить её не туда.
39
+
36
40
  ## Порядок
37
41
 
38
42
  Правка ресурса доезжает до дерева только через сборку пакета: строка запуска читает собранное,
@@ -46,7 +50,7 @@ npx agent-kit doctor # что разложено, что отстало,
46
50
  npx agent-kit sync # разложить
47
51
  npx agent-kit sync --check # ничего не писать, отказать при расхождении
48
52
  npx agent-kit stats # чем пользовались, чем ни разу, обо что спотыкались
49
- npx agent-kit propose # отправить предложения, адресованные пакету
53
+ npx agent-kit propose # отправить груз в приём: сводку, предложения и разборы
50
54
  ```
51
55
 
52
56
  ## Обратная связь наверх
@@ -62,11 +66,29 @@ npx agent-kit propose # отправить предложения, адр
62
66
 
63
67
  **Предложения** приносит разбор закрытой задачи — командой `/skill-curator`. Каждому он ставит
64
68
  адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
65
- (форма — шаблон `proposal.md`), а `agent-kit propose` отправляет наружу те, что адресованы
66
- пакету, вместе со сводкой. Текст с адресом этого дерева отбивает отправку целиком.
67
-
68
- Разбираются они в репозитории самого пакета — командой `/agent-kit-digest`, там же, где лежат
69
- правимые ресурсы и видно всех потребителей сразу.
69
+ (форма — шаблон `proposal.md`), а `agent-kit propose` увозит в приём те, что адресованы
70
+ пакету, вместе со сводкой и разборами происшествий. Адрес дерева в сводке или в тексте
71
+ предложения отбивает отправку целиком.
72
+
73
+ Приём закрытая служба: сводка говорит о рабочих привычках команды, и в открытой очереди работ
74
+ это выложено всему свету. Адрес приёма объявляется ключом `intake` в конфиге дерева, токен —
75
+ ключом `token`, и лежит он вне дерева.
76
+
77
+ **Отметка об отправке в файле предложения — след для человека, а не хранилище состояния.** Файл
78
+ живёт в рабочем дереве, а дерево у каждой ветки своё: отметка, поставленная в одной ветке, в
79
+ соседней не видна, и тот же текст уезжает вторым разом. Второй записью он при этом не
80
+ становится — приём отбирает уже приехавшее по признаку предложения, и его ответ говорит,
81
+ сколько записей легло и сколько уже лежало. Строка «принято 0, уже лежало 3» означает, что
82
+ нового не уехало ничего.
83
+
84
+ Разбираются предложения в репозитории самого пакета — командой `/agent-kit-digest`, там же, где
85
+ лежат правимые ресурсы и видно всех потребителей сразу.
86
+
87
+ **Имя файла предложения в текстах дерева не называется.** Каталог предложений в историю не едет:
88
+ файл лежит на той машине, где его написали, и адрес на него ведёт в пустоту у всех остальных —
89
+ проверка путей краснеет в каждом дереве, кроме одного, а читателю ссылка не даёт ничего.
90
+ Написанное в разборе происшествия и в любом другом тексте репозитория говорит, кому предложение
91
+ отправлено и о чём оно; ресурс пакета при этом называть можно — он в истории есть.
70
92
 
71
93
  Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой
72
94
  не приходит: замечание было прочитано, процитировано владельцу и нарушено в том же ходе —
@@ -74,6 +96,14 @@ npx agent-kit propose # отправить предложения, адр
74
96
  только войдя в ресурс пакета; до этого на него не ссылаются как на действующее требование и не
75
97
  считают дырку закрытой.
76
98
 
99
+ **Слово владельца о предложении — «отправь», «заведи», «напиши пропозал» и любая другая форма
100
+ того же — исполняется отправкой в тот же ход.** Сухой прогон отправкой не является: он
101
+ показывает, что уехало бы, ничего не заводит и следа наружу не оставляет. Неудобна отправка
102
+ ровно в одном месте — она пишет отметки в файлы предложений и делает дерево грязным; при
103
+ открытом PR отметки ложатся вторым коммитом в ту же ветку, и это их место, а не повод
104
+ отложить. Стережёт это гард предложения на завершении хода — там же, где стоит гард
105
+ происшествия, и по той же причине.
106
+
77
107
  ## Установка туда, где уже всё своё
78
108
 
79
109
  1. `init`, затем `skip` на всё, что дерево держит само. Пустая раскладка — законное начало.
@@ -83,6 +113,27 @@ npx agent-kit propose # отправить предложения, адр
83
113
  4. Разложенное поверх своего пакет не пишет: файл без шапки для него чужой. Снять его —
84
114
  решение владельца, и до этого раскладка отказывает поимённо.
85
115
 
116
+ ## Свойства дерева
117
+
118
+ Часть правил пакета верна только там, где есть хранилище, админка или приложение. Дерево
119
+ перечисляет, что у него есть, ключом `has`; ресурс называет нужное ему свойство приставкой в
120
+ имени — `observability.needs-app.md`, — и дереву, которое такого свойства не назвало, не
121
+ кладётся вовсе: ни он сам, ни черновик его компаньона.
122
+
123
+ ```json
124
+ { "has": ["packages", "app"] }
125
+ ```
126
+
127
+ - **Молчание требованию не отвечает.** Дерево с пустым `has` не получает ни одного помеченного
128
+ ресурса: положенный наугад, он вернётся пустым компаньоном, заполнить который нечем.
129
+ - **Требование — не вид.** Вид отвечает на «какой из трёх» и выбирается один; свойств у дерева
130
+ сразу несколько, и дерево, которое публикует пакеты и держит приложение, называет оба.
131
+ - **`only` сильнее требования.** Ресурс, названный поимённо, ложится и при неотвеченном
132
+ требовании; перечень раскладки называет это вслух, а отказ по его пустому компаньону зовёт
133
+ снять ресурс, а не заполнять черновик.
134
+ - **Свойство, которого пакет не объявлял, роняет раскладку** — что в `has` дерева, что в имени
135
+ ресурса. Объявлены свойства перечнем при пакете, рядом с осями различия.
136
+
86
137
  ## Ловушки
87
138
 
88
139
  - **Правила и паттерны при отвергнутом законе в отказе не перечисляются.** Их снимает каскад, а
@@ -108,10 +159,11 @@ npx agent-kit propose # отправить предложения, адр
108
159
  написанная по путям, требует под него доменное правило — а оно уводит править файл на месте.
109
160
  Правка на месте теряется на следующей раскладке, и до тех пор выглядит применённой. Ветка по
110
161
  шапке ставится в карте первой и решает раньше путей.
111
- - **Настройки проверок сливаются на один уровень.** Верхние ключи `checks.json` ложатся поверх
112
- умолчаний по одному, а вложенный объект замещается целиком: назвав один ключ борды, дерево
113
- теряет остальные и увидит это отказом «нет токена бота», то есть как неполадку машины.
114
- Вложенный раздел заполняется целиком либо не заводится вовсе.
162
+ - **Настройки проверок сливаются по ключам, а списки замещаются.** Объект `checks.json`
163
+ ложится поверх умолчания ключ за ключом на любой глубине: назвав один ключ борды, дерево не
164
+ теряет соседних. Список приходит целиком назвав корни исходников, дерево получает ровно
165
+ названное, а не умолчание вместе со своим: «дописать в список» и «убрать из списка» в этой
166
+ записи неразличимы.
115
167
  - **Утверждение правила переезжает вместе с кодом.** Вынесенное в надстройку перестаёт
116
168
  находиться по прежнему символу, и привязка в спутнике правила врёт молча — сверка спеков
117
169
  ловит это, но только если её позвать.
@@ -0,0 +1,14 @@
1
+ {
2
+ "db": {
3
+ "title": "хранилище: схема, миграции, записи предметной области"
4
+ },
5
+ "admin": {
6
+ "title": "админка: экраны правки записей и роли доступа"
7
+ },
8
+ "app": {
9
+ "title": "приложение: экраны, которыми пользуются люди"
10
+ },
11
+ "packages": {
12
+ "title": "публикуемые пакеты: реестр, версии, журнал изменений"
13
+ }
14
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAcA,OAAO,EAAqC,iBAAiB,EAA8B,MAAM,oBAAoB,CAAC;AA6LtH,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiE9E"}
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;AAqM7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsE9E"}
package/bin/agent-kit.js CHANGED
@@ -10,10 +10,12 @@ import { readFileSync } from 'node:fs';
10
10
  import { dirname, join, resolve } from 'node:path';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import process from 'node:process';
13
+ import { unknownFlagsIn } from '../lib/argv.js';
13
14
  import { readCatalog, resolveSelection } from '../lib/catalog.js';
14
- import { adopt, doctor, init, list, propose, stats, sync } from '../lib/commands.js';
15
+ import { adopt, doctor, init, list, stats, sync } from '../lib/commands.js';
16
+ import { httpShip } from '../lib/ship.js';
17
+ import { propose } from '../lib/shipment.js';
15
18
  import { DEFAULT_DAYS } from '../lib/observations.js';
16
- import { ghIssue, repositoryOf } from '../lib/submit.js';
17
19
  import { staleBuild } from '../lib/freshness.js';
18
20
  import { packageRootFrom } from '../lib/package-root.js';
19
21
  import { readAxes } from '../lib/variants.js';
@@ -29,7 +31,7 @@ const USAGE = [
29
31
  ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',
30
32
  ' stats --days N за сколько дней; без довода — за три',
31
33
  ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',
32
- ' propose отправить предложения с адресом «пакет» в очередь работ пакета',
34
+ ' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',
33
35
  ' propose --dry-run показать, что уехало бы, и ничего не отправлять',
34
36
  ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',
35
37
  '',
@@ -46,6 +48,17 @@ const USAGE = [
46
48
  ' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',
47
49
  ' без флага спросить; без терминала — отказ, кроме `--all`',
48
50
  ];
51
+ /**
52
+ * Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без
53
+ * пометки этот путь читался бы как ещё один незнакомый довод.
54
+ */
55
+ const PROPOSE_FLAGS = ['--dry-run', '--root <>'];
56
+ /** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */
57
+ const PROPOSE_USAGE = [
58
+ ' propose отправить груз в приём',
59
+ ' propose --dry-run показать, что уехало бы, и ничего не отправлять',
60
+ ' --root <путь> корень проекта; по умолчанию текущий каталог',
61
+ ];
49
62
  /**
50
63
  * Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только
51
64
  * здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,
@@ -61,9 +74,6 @@ function environmentOf(root) {
61
74
  // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.
62
75
  // У потребителя исходников рядом нет, и сверка молчит.
63
76
  stale: staleBuild(pkg, manifest.name),
64
- // Куда уезжают предложения. Читается из манифеста: зашитый в код адрес назвал бы чужое
65
- // дерево в текстах пакета — и врал бы у всякого, кто пакет форкнул.
66
- repository: repositoryOf(manifest.repository?.url ?? ''),
67
77
  };
68
78
  }
69
79
  /** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */
@@ -202,19 +212,24 @@ export async function main(argv) {
202
212
  });
203
213
  }
204
214
  case 'propose': {
205
- // Сводка едет вместе с предложением: без цифр оно читается как мнение. Берётся тем
206
- // же отрезком, что и сводка по умолчанию, предложение пишут по свежей задаче.
207
- const summary = stats(env, {
208
- days: DEFAULT_DAYS,
209
- today: new Date().toISOString().slice(0, 10),
210
- json: false,
211
- });
215
+ // Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый
216
+ // довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в
217
+ // приём всё накопленное, и по выводу это не отличалось от «команда ничего не
218
+ // сделала». Прочие команды такого разбора не знают — их действие обратимо.
219
+ const unknown = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);
220
+ if (unknown.length) {
221
+ return {
222
+ code: 1,
223
+ lines: [`таких доводов у \`propose\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],
224
+ };
225
+ }
212
226
  return propose(env, {
213
227
  dryRun: argv.includes('--dry-run'),
214
- submit: ghIssue,
215
- repository: env.repository ?? '',
228
+ ship: httpShip,
216
229
  remote: remoteOf(env.root),
217
- summary: summary.lines,
230
+ // Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.
231
+ days: DEFAULT_DAYS,
232
+ today: new Date().toISOString().slice(0, 10),
218
233
  });
219
234
  }
220
235
  case 'doctor':
@@ -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 { IEntryOfCatalog, readCatalog, resolveSelection } from '../lib/catalog.js';\nimport { adopt, doctor, IEnvironment, init, IOutcomeOfCommand, list, propose, stats, sync } from '../lib/commands.js';\nimport { DEFAULT_DAYS } from '../lib/observations.js';\nimport { ghIssue, repositoryOf } from '../lib/submit.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 '',\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 * Единственное место, где пакет узнаёт собственное расположение. `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; repository?: { url?: string } } = JSON.parse(\n readFileSync(join(pkg, 'package.json'), 'utf8')\n ) as {\n name: string;\n version: string;\n repository?: { url?: 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 repository: repositoryOf(manifest.repository?.url ?? ''),\n };\n}\n\n/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */\nfunction remoteOf(root: string): string {\n try {\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 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 spoken: string = optionOf(argv, `--${axis.name}`, '');\n const known: (value: string) => boolean = (value: string): boolean =>\n axis.options.some((option: IOptionOfAxis): boolean => option.value === value);\n\n if (spoken) {\n if (!known(spoken)) {\n return {\n code: 1,\n lines: [\n `такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`,\n `есть: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n chosen[axis.name] = spoken;\n continue;\n }\n\n if (argv.includes('--all')) {\n chosen[axis.name] = axis.options[0]?.value ?? '';\n continue;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n `назови вид флагом \\`--${axis.name} <вид>\\`: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n\n const answer: string | null = await askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n if (answer === null) {\n return null;\n }\n chosen[axis.name] = answer;\n }\n\n return chosen;\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\n switch (command) {\n case 'init': {\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 case 'list':\n return list(env);\n case 'sync':\n return sync(env, argv.includes('--check'));\n case 'stats': {\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 case 'propose': {\n // Сводка едет вместе с предложением: без цифр оно читается как мнение. Берётся тем\n // же отрезком, что и сводка по умолчанию, — предложение пишут по свежей задаче.\n const summary: IOutcomeOfCommand = stats(env, {\n days: DEFAULT_DAYS,\n today: new Date().toISOString().slice(0, 10),\n json: false,\n });\n\n return propose(env, {\n dryRun: argv.includes('--dry-run'),\n submit: ghIssue,\n repository: env.repository ?? '',\n remote: remoteOf(env.root),\n summary: summary.lines,\n });\n }\n case 'doctor':\n return doctor(env);\n case 'adopt':\n return adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n );\n default:\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\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 { httpShip } from '../lib/ship.js';\nimport { propose } 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 '',\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 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 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 spoken: string = optionOf(argv, `--${axis.name}`, '');\n const known: (value: string) => boolean = (value: string): boolean =>\n axis.options.some((option: IOptionOfAxis): boolean => option.value === value);\n\n if (spoken) {\n if (!known(spoken)) {\n return {\n code: 1,\n lines: [\n `такого вида по оси «${axis.name}» пакет не везёт: ${spoken}`,\n `есть: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n chosen[axis.name] = spoken;\n continue;\n }\n\n if (argv.includes('--all')) {\n chosen[axis.name] = axis.options[0]?.value ?? '';\n continue;\n }\n\n if (!canAsk()) {\n return {\n code: 1,\n lines: [\n 'спросить некого: запуск без терминала',\n `назови вид флагом \\`--${axis.name} <вид>\\`: ${axis.options.map((option: IOptionOfAxis): string => option.value).join(', ')}`,\n ],\n };\n }\n\n const answer: string | null = await askOne(\n axis.options.map((option: IOptionOfAxis): IChoice => ({ id: option.value, name: option.value, title: option.title })),\n axis.question\n );\n if (answer === null) {\n return null;\n }\n chosen[axis.name] = answer;\n }\n\n return chosen;\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\n switch (command) {\n case 'init': {\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 case 'list':\n return list(env);\n case 'sync':\n return sync(env, argv.includes('--check'));\n case 'stats': {\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 case 'propose': {\n // Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый\n // довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в\n // приём всё накопленное, и по выводу это не отличалось от «команда ничего не\n // сделала». Прочие команды такого разбора не знают — их действие обратимо.\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 case 'doctor':\n return doctor(env);\n case 'adopt':\n return adopt(\n env,\n argv.slice(1).filter((value: string): boolean => !value.startsWith('--') && value !== optionOf(argv, '--root', ''))\n );\n default:\n return { code: command ? 1 : 0, lines: command ? [`неизвестная команда «${command}»`, '', ...USAGE] : USAGE };\n }\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/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './lib/assets.js';
2
+ export * from './lib/cargo.js';
2
3
  export * from './lib/catalog.js';
3
4
  export * from './lib/commands.js';
4
5
  export * from './lib/config.js';
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './lib/assets.js';
2
+ export * from './lib/cargo.js';
2
3
  export * from './lib/catalog.js';
3
4
  export * from './lib/commands.js';
4
5
  export * from './lib/config.js';
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../projects/agent-kit/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './lib/assets.js';\nexport * from './lib/cargo.js';\nexport * from './lib/catalog.js';\nexport * from './lib/commands.js';\nexport * from './lib/config.js';\nexport * from './lib/picker.js';\nexport * from './lib/plan.js';\nexport * from './lib/sections.js';\nexport * from './lib/stamp.js';\nexport * from './lib/sync.js';\nexport * from './lib/vars.js';\nexport * from './lib/freshness.js';\n"]}
package/lib/argv.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Разбор доводов командной строки.
3
+ *
4
+ * Команда, которая молча пропускает незнакомый довод, отвечает одинаково на «довод лишний» и на
5
+ * «команда ничего не сделала». Там, где единственное действие обратимо, разница стоит повторного
6
+ * запуска; там, где оно необратимо и уходит наружу, — стоит отправленного груза: вызов с
7
+ * доводом справки, сделанный ради списка режимов, отправил в приём всё накопленное.
8
+ */
9
+ /**
10
+ * Доводы вызова, которых команда не знает.
11
+ *
12
+ * Значение, стоящее за доводом с параметром, доводом не считается: `--root /путь` — это один
13
+ * довод и его значение, а не два незнакомых. Набор известных перечисляет и те доводы, что
14
+ * значение принимают, и те, что нет: у пустого набора незнакомо всё, начинающееся с дефиса.
15
+ */
16
+ export declare function unknownFlagsIn(argv: readonly string[], known: readonly string[]): readonly string[];
17
+ //# sourceMappingURL=argv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/argv.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CA6BnG"}