@rt-tools/agent-kit 0.4.0 → 0.5.1

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 (52) hide show
  1. package/README.md +5 -0
  2. package/assets/checks/board.github.mjs +45 -2
  3. package/assets/checks/check-board.github.mjs +7 -14
  4. package/assets/checks/check-doc-paths.mjs +200 -30
  5. package/assets/checks/check-specs.mjs +131 -17
  6. package/assets/checks/rt-kit-checks.config.mjs +12 -0
  7. package/assets/commands/next-session.md +122 -0
  8. package/assets/defaults/gate-map.sh +29 -3
  9. package/assets/defaults/project.sh +50 -0
  10. package/assets/docs/GLOSSARY.md +74 -0
  11. package/assets/hooks/git-guard-delivery.sh +87 -4
  12. package/assets/hooks/grill-gate.sh +96 -0
  13. package/assets/hooks/task-flow-guard.sh +14 -3
  14. package/assets/hooks/window-fill-guard.sh +150 -0
  15. package/assets/laws/code-structure.md +10 -0
  16. package/assets/laws/delivery.md +8 -1
  17. package/assets/laws/project-documentation.md +14 -0
  18. package/assets/laws/verifiability.md +13 -0
  19. package/assets/laws/work-conduct.md +19 -0
  20. package/assets/patterns/git-workflow-commit.github.md +4 -0
  21. package/assets/patterns/spec-driven-domain.md +35 -0
  22. package/assets/patterns/task-flow-close.md +72 -8
  23. package/assets/patterns/task-flow-handoff.md +115 -0
  24. package/assets/patterns/task-flow-resume.md +2 -2
  25. package/assets/patterns/task-flow-start.md +18 -2
  26. package/assets/rules/angular-patterns.md +4 -0
  27. package/assets/rules/browser-verification.md +4 -3
  28. package/assets/rules/doc-style.md +53 -1
  29. package/assets/rules/git-workflow.azure.md +24 -0
  30. package/assets/rules/git-workflow.github.md +23 -0
  31. package/assets/rules/git-workflow.gitlab.md +23 -0
  32. package/assets/rules/spec-driven.md +19 -1
  33. package/assets/rules/task-flow.md +88 -2
  34. package/assets/skills/agent-kit.md +4 -0
  35. package/assets/templates/rule.md +1 -1
  36. package/lib/commands.d.ts.map +1 -1
  37. package/lib/commands.js +2 -1
  38. package/lib/commands.js.map +1 -1
  39. package/lib/config.d.ts +3 -1
  40. package/lib/config.d.ts.map +1 -1
  41. package/lib/config.js +2 -0
  42. package/lib/config.js.map +1 -1
  43. package/lib/hooks-map.d.ts +20 -5
  44. package/lib/hooks-map.d.ts.map +1 -1
  45. package/lib/hooks-map.js +56 -15
  46. package/lib/hooks-map.js.map +1 -1
  47. package/lib/sync.d.ts.map +1 -1
  48. package/lib/sync.js +2 -5
  49. package/lib/sync.js.map +1 -1
  50. package/package.json +1 -1
  51. package/rt-tools-agent-kit-0.5.1.tgz +0 -0
  52. package/rt-tools-agent-kit-0.4.0.tgz +0 -0
@@ -31,19 +31,67 @@ description: Правило под «Закон о ведении работы»
31
31
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
32
32
  же дереве, которое держит код иначе.
33
33
 
34
+ ## Шаги работы
35
+
36
+ Счёт сплошной: номер шага один на весь путь и не начинается заново в каждом паттерне. Шаг
37
+ называют номером вслух, и два разных первых шага мешают разговору; а пропущенный шаг виден
38
+ только по списку, из которого он выпал.
39
+
40
+ | Шаг | Что происходит | Ведёт паттерн |
41
+ | --- | -------------------------------------------------------- | ------------------- |
42
+ | 1 | Разведка по дереву — до первого вопроса владельцу | `task-flow-start` |
43
+ | 2 | Разбор просьбы с владельцем, шесть обязательных вопросов | `task-flow-start` |
44
+ | 3 | Конвейер ролей после разбора | `task-flow-start` |
45
+ | 4 | Задача, ветка, папка задачи | `task-flow-start` |
46
+ | 5 | Шапка замысла и сам замысел | `task-flow-start` |
47
+ | 6 | Возвращение к работе новым заходом | `task-flow-resume` |
48
+ | 7 | Этап замысла делается и отмечается в ходе работы | `task-flow-resume` |
49
+ | 8 | Заход закрывается передачей | `task-flow-handoff` |
50
+ | 9 | Договорённость вливается в спек домена | `task-flow-close` |
51
+ | 10 | Тексты домена приводятся к сделанному | `task-flow-close` |
52
+ | 11 | Папка задачи разбирается | `task-flow-close` |
53
+ | 12 | Сверка очереди работ | `task-flow-close` |
54
+
55
+ Шаги 6–8 повторяются, пока этапы замысла не кончатся: первый заход входит в работу шагом 1 и
56
+ доходит до 7, дальше каждый следующий начинается шагом 6. Шаги 9–12 идут один раз, когда работа
57
+ кончена.
58
+
59
+ Список показывается владельцу в начале работы, и на нём же отмечается, где стоим: иначе после
60
+ шести вопросов не видно ни того, что будет дальше, ни сколько всего впереди.
61
+
34
62
  ## Как закон применяется здесь
35
63
 
36
64
  - **Правка кода приложения отбивается, пока на диске нет замысла.** Гард требует папку задачи
37
65
  по имени ветки, `plan.md` в ней и названную в его шапке договорённость о продукте.
66
+ - **Влитая договорённость ветку не запирает.** После вливания директории «предложено» на диске
67
+ нет, а замысел на неё ссылается до конца работы: гард отличает влитое от незаведённого по
68
+ истории ветки и пропускает первое. Иначе последний коммит отчёта закрывал бы дорогу правкам
69
+ по замечаниям разбора.
38
70
  - **Договорённость требуется по путям правки, а не по оценке задачи.** `apps/**` и `libs/**`
39
71
  — признак; правила, тексты, обвязка и зависимости под него не подпадают. Обход — строка
40
72
  `**Поведение:** не меняется — <причина владельца>` в замысле; пустая причина не
41
73
  принимается.
74
+ - **Ход, в котором владельцу задан вопрос, не заканчивается, пока за этот же ход не читались
75
+ законы и правила.** Чтением считается любой из трёх путей: загрузка правила, чтение файла
76
+ законов или правил, поиск по ним. Отбивает гард разговора — на завершении хода, а не на
77
+ инструменте вопроса: спрашивают чаще прозой, чем меню. Найденное ложится в раздел «Что уже
78
+ сказано в правилах» разбора.
42
79
  - **Состояние незаконченной работы приходит в контекст на запуске сессии.** Замысел и ход
43
80
  работы отдаются целиком, разбор просьбы — путём. Ветка вида `<КЛЮЧ>-*` без папки даёт
44
81
  предупреждение с готовой командой, но сессию не рвёт.
45
82
  - **Сделанное отмечается только в ходе работы.** «Где стоим» перезаписывается каждым заходом,
46
83
  а не дописывается: это первое, что читает следующий заход.
84
+ - **Заполнение окна захода стережёт гард, а не память исполнителя.** На первом пороге он
85
+ напоминает выбирать точку остановки, на втором отбивает всё, кроме записи хода работы,
86
+ передачи и команд поставки. Размер окна и оба порога дерево задаёт само; не задавшее размера
87
+ стража не получает.
88
+ - **Заход закрывается передачей, которая лежит вне дерева.** Состояние работы коммитится ходом
89
+ работы, а передача его пересказывает для вставки в новый заход: рабочее дерево, ветка,
90
+ сделанное, следующий шаг и особенности захода. В историю она не едет — иначе рядом с ходом
91
+ работы заводится вторая запись об одном и том же.
92
+ - **Слово для нового понятия ищется в словаре дерева.** Общую часть словаря везёт пакет,
93
+ предметную дописывает дерево надстройкой; словарь уезжает в контекст на запуске сессии
94
+ целиком, поэтому «не читал» основанием не бывает.
47
95
  - **Папка задачи заводится черновиком и получает номер командой.** До конца разбора
48
96
  неизвестно, сколько задач из него выйдет, поэтому номер не может быть первым;
49
97
  `npm run task:new` переименовывает черновик и проставляет шапку замысла.
@@ -55,6 +103,19 @@ description: Правило под «Закон о ведении работы»
55
103
  - **Папка закрытой задачи разбирается, а не переносится целиком.** В `docs/archive/` уезжает
56
104
  то, что объясняет состоявшееся решение; остальное удаляется. Неразобранную ловит сверка
57
105
  очереди работ.
106
+ - **Слияние отбивается, пока ветка везёт папку своей задачи.** Требование стоит на слиянии, а
107
+ не на открытии отчёта: до слияния папка ещё нужна — правка по замечаниям разбора идёт в ту
108
+ же ветку, а без замысла на диске её отбивает гард хода работы. На открытии отчёта о лежащей
109
+ папке говорится вслух, и только. Судится содержимое ветки, а не рабочее дерево: снесённая,
110
+ но не закоммиченная папка въехала бы вместе с веткой.
111
+ - **Ветка, снёсшая папку, обязана прибавить запись в архив.** Снести дешевле, чем разобрать, и
112
+ первым уходит разбор просьбы — единственная запись слов владельца. Что именно увезено,
113
+ требование не судит: это судит владелец.
114
+ - **Обход — строка `Task-folder-skip: <причина>` в отчёте или в самой команде слияния.**
115
+ Работа, вливаемая частями, папку до конца не разбирает. Чтение из команды работает и без
116
+ сети: единственный сетевой путь отбивал бы оффлайн то самое слияние, причина которого
117
+ написана в отчёте. Пустая причина обходом не считается, а сам обход снимает отказ, но не
118
+ гасит строку сверки очереди — иначе он через месяц становится рабочим путём.
58
119
 
59
120
  ## Чего из закона здесь нет
60
121
 
@@ -78,14 +139,24 @@ description: Правило под «Закон о ведении работы»
78
139
  остальные тексты, и правка по ходу отличима от первоначальной записи только по истории.
79
140
  Держится это тем же, чем и порядок разбора.
80
141
 
81
- Разбор папки при закрытии не проверяется по существу: сверка очереди работ видит, что папка
82
- закрытой задачи лежит на месте, но не судит, что из неё стоило увезти в архив.
142
+ Приведение текстов к сделанному не проверяет ничто, и проверки на него не будет: что устарело
143
+ в правиле и в спеке, машине не видно раздел «Чего из закона здесь нет» не читает ни одна
144
+ сверка, а «Что не входит» выглядит верным ровно так же, как в день, когда его писали. Держится
145
+ это шагом закрытия работы и следом задачи в замысле: там названо, что перечитать. Правило и
146
+ спек правятся в ветке, закон — нет: его статья приносится владельцу текстом, а работа идёт
147
+ дальше без неё.
148
+
149
+ Что именно перенесли в архив, не проверяется. Гард видит, что папка уезжает в главную ветку и
150
+ что ветка что-то в архив добавила, но не может судить, то ли это и стоило ли переносить именно
151
+ это. Сверять содержимое машине нечем — смотрит владелец на ревью. Отсюда же и обход: если
152
+ работа вливается частями, папку до конца не разбирают, а причина остаётся в отчёте.
83
153
 
84
154
  ## Паттерны
85
155
 
86
156
  - `task-flow-start` — разведка, разбор, договорённость, замысел, задача и ветка.
87
157
  - `task-flow-resume` — возвращение к незаконченной работе новым заходом.
88
158
  - `task-flow-close` — вливание договорённости, разбор папки, переезд в архив.
159
+ - `task-flow-handoff` — закрытие захода по заполнению окна: точка остановки и передача.
89
160
 
90
161
  ## Ловушки
91
162
 
@@ -105,6 +176,21 @@ description: Правило под «Закон о ведении работы»
105
176
  - **Субагент вопросов владельцу не задаёт.** Ни роли, ни конвейер до него не достучатся —
106
177
  они возвращают текст главному агенту. Поэтому разбор ведёт главный агент, а роли стоят по
107
178
  обе стороны от него.
179
+ - **Если дефект чинится правкой одного общего числа, спроси владельца, тем ли способом ты его
180
+ чинишь.** Замер показывает, что дефект ушёл, — но не то, что причину вылечили. В одной
181
+ задаче так ушли две правки подряд: сначала подняли общее число у соседнего узла, потом
182
+ перенесли узел в другое место разметки. Обе владелец отверг, а нужный способ назвал сам.
183
+ Спрашивают до правки, а не показывают замер после.
184
+ - **Линия работ по теме читается до того, как решается раскладка.** Файл линии держит решения,
185
+ которые пережили десяток задач, и разведка по коду их не находит: снятое решение следа в
186
+ дереве не оставляет. Домен, заведённый генератором и снесённый через полчаса, стоял в линии
187
+ прямым запретом — но линию открыли уже после того, как он был заведён во второй раз.
188
+ - **Работа, которая разбирает папку задачи, своей папки не заводит.** Иначе она снимает одну и
189
+ оставляет вторую, сверка очереди краснеет на неё, и следующая работа повторяет то же — круг
190
+ не кончается. Так и вышло: разбор папки закрытой работы завёл себе папку, и на неё тут же
191
+ пришлось заводить третью задачу. Замысел на диске требует гард, и требует он его только под
192
+ правку кода приложения; разбор папок туда не доходит, а понимание такой работы целиком
193
+ помещается в тело отчёта.
108
194
  - **Слово для нового понятия берётся из `docs/GLOSSARY.md` или заводится там же.** Третий файл
109
195
  папки задачи называется `progress.md`, а не `journal.md`, ровно поэтому: журнал в этом
110
196
  дереве один, и он другой.
@@ -57,6 +57,10 @@ npx agent-kit sync --check # ничего не писать, отказать
57
57
 
58
58
  ## Ловушки
59
59
 
60
+ - **Линтер по следам правки судит файл целиком, а не внесённую правку.** Импорт, добавленный
61
+ отдельным шагом, отбивается как неиспользуемый ещё до того, как появится строка, которая его
62
+ зовёт, и работа встаёт на половине. Правка делается одним вызовом либо в порядке «сначала
63
+ использование, потом импорт».
60
64
  - **Прогонять сценарии гардов можно, ничего не раскладывая.** Обвязка набора принимает каталог
61
65
  гардов переменной, и пакетную редакцию гоняют по сценариям дерева до установки. Заход,
62
66
  потраченный на диагноз по последствиям, стоил ровно этой строки.
@@ -15,7 +15,7 @@ description: Правило под закон «<Название закона>
15
15
 
16
16
  <Правка, по которой правило узнаётся. Гейт зовёт его по этому признаку, а не по названию.>
17
17
 
18
- ## Что здесь действует
18
+ ## Как закон применяется здесь
19
19
 
20
20
  Каждый пункт начинается жирной статьёй, и у каждой статьи есть строка в `implementation.md`
21
21
  рядом. Утверждение, которому места в коде не нашлось, сюда не ставится: оно уходит прозой в
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO7C,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;AAoDD,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,MAAyB,CAAC;AAuFpD;;;;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;AAgBD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA2EzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CA+CpF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2C3D;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAkDzD"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO7C,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;AAqDD,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,MAAyB,CAAC;AAyFpD;;;;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;AAgBD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA2EzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CA+CpF;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2C3D;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAkDzD"}
package/lib/commands.js CHANGED
@@ -50,6 +50,7 @@ const KIND_TITLE = {
50
50
  commands: 'КОМАНДЫ',
51
51
  workflows: 'ВОРКФЛОУ',
52
52
  templates: 'ШАБЛОНЫ',
53
+ docs: 'ДОКУМЕНТЫ',
53
54
  };
54
55
  /** Состояние компаньона словами. У заполненного слова нет: о нём говорить нечего. */
55
56
  const COMPANION_WORD = {
@@ -97,7 +98,7 @@ const gapLines = (result) => result.gaps.flatMap((gap) => [
97
98
  const unboundLines = (result) => result.unbound.length
98
99
  ? [
99
100
  `гарды разложены, но в \`${SETTINGS_PATH}\` их не зовёт никто: ${result.unbound.length}`,
100
- ...result.unbound.map((binding) => ` ${binding.path} — ${binding.event} ${binding.matcher}`),
101
+ ...result.unbound.map((binding) => ` ${binding.path} — ${binding.event}${binding.matcher ? ` ${binding.matcher}` : ''}`),
101
102
  ` вставь в \`${SETTINGS_PATH}\` раздел \`hooks\` — готовый кусок ниже:`,
102
103
  ...JSON.stringify({ hooks: hooksSection(result.unbound) }, null, 4)
103
104
  .split('\n')
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Команды и их вывод. Печать отделена от работы: команда возвращает строки и код возврата,\n * а `process.exit` зовёт только точка входа — иначе ни одну из них нельзя было бы проверить\n * спекой, не перехватывая поток вывода.\n */\nimport { existsSync, mkdirSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { collectAssets } from './assets.js';\nimport { IEntryOfCatalog, IGapOfVariant, isChosen, readCatalog } from './catalog.js';\nimport { ICompanion, isUnfilled, TCompanionState } from './companion.js';\nimport { CONFIG_PATH, DEFAULT_LAYOUT, IConfig, KINDS, OVERRIDES_DIR, readConfig, TKind } from './config.js';\nimport { IStaleBuild } from './freshness.js';\nimport { hooksSection, IHookBinding, SETTINGS_PATH } from './hooks-map.js';\nimport { IPlanned, isRefusal, TOutcome } from './plan.js';\nimport { ISyncResult, pendingOf, planSync, runSync } from './sync.js';\nimport { placeholdersOf } from './vars.js';\nimport { IAxis, IOptionOfAxis, readAxes, unansweredAxes } from './variants.js';\n\nexport interface IOutcomeOfCommand {\n readonly code: number;\n readonly lines: readonly string[];\n}\n\n/** Всё, что команда знает о мире: корень проекта, версия пакета и его каталог ресурсов. */\nexport interface IEnvironment {\n readonly root: string;\n readonly version: string;\n readonly assetsDir: string;\n /**\n * Ресурсы правлены позже, чем собран пакет, из которого идёт раскладка; `null` — сверять не с\n * чем. Считается на краю, где пакет знает своё расположение: библиотечные модули работают с\n * тем каталогом ресурсов, который им дали, и о существовании исходников не знают.\n */\n readonly stale?: IStaleBuild | null;\n}\n\n/** Что с файлом сделала раскладка. Прошедшее время здесь правда: `sync` уже записал. */\nconst DONE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'положен',\n update: 'переложен',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'без изменений',\n};\n\n/**\n * Что с файлом **сейчас**. Отдельно от прошедшего времени потому, что `doctor` и `list` ничего\n * не пишут: сказать «положен» о файле, которого в дереве нет, значит соврать читателю ровно там,\n * где он пришёл узнать состояние.\n */\nconst STATE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'нет в дереве',\n update: 'отстал от пакета',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'на месте',\n};\n\nconst NOT_CHOSEN: string = 'не выбран';\nconst SKIPPED: string = 'пропущен';\n/** Ресурс чужого вида: в этом дереве его не существует, а не «от него отказались». */\nconst OTHER_VARIANT: string = 'другой вид';\n\nconst KIND_TITLE: Readonly<Record<TKind, string>> = {\n laws: 'ЗАКОНЫ',\n rules: 'ПРАВИЛА',\n patterns: 'ПАТТЕРНЫ',\n skills: 'СКИЛЫ',\n hooks: 'ХУКИ',\n defaults: 'УМОЛЧАНИЯ',\n checks: 'ПРОВЕРКИ',\n agents: 'АГЕНТЫ',\n commands: 'КОМАНДЫ',\n workflows: 'ВОРКФЛОУ',\n templates: 'ШАБЛОНЫ',\n};\n\n/** Состояние компаньона словами. У заполненного слова нет: о нём говорить нечего. */\nconst COMPANION_WORD: Readonly<Record<TCompanionState, string>> = {\n missing: 'пропал',\n draft: 'остался черновиком',\n filled: 'заполнен',\n};\n\nconst NO_CONFIG: string = `нет \\`${CONFIG_PATH}\\` — начни с \\`agent-kit init\\``;\n\n/** Куда уезжает прежнее содержимое файла, отданного пакету. */\nexport const KEPT_SUFFIX: string = '.before-rt-kit';\n\nconst holes: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n [...result.missing].map(\n ([asset, names]: [string, readonly string[]]): string =>\n ` ${asset}: нет значений для ${names.map((name: string): string => `{{${name}}}`).join(', ')}`\n );\n\nconst unfilled: (result: ISyncResult) => readonly ICompanion[] = (result: ISyncResult): readonly ICompanion[] =>\n result.companions.filter(isUnfilled);\n\n/** Ось без ответа: чем её спрашивают и из чего выбирают. */\nconst axisLines: (axes: readonly IAxis[]) => string[] = (axes: readonly IAxis[]): string[] =>\n axes.flatMap((axis: IAxis): string[] => [\n ` ${axis.name} — ${axis.question}`,\n ...axis.options.map((option: IOptionOfAxis): string => ` ${option.value.padEnd(8)} ${option.title}`),\n ` выбор пишется в \\`variants\\` конфига: {\"${axis.name}\": \"${axis.options[0]?.value ?? ''}\"}`,\n ]);\n\n/**\n * Брошенное: файл лежит, а ресурс за ним больше не берут. Печатается отдельным списком и с\n * подсказкой — стереть его пакет не вправе, а промолчать не может: агент читает такой файл как\n * действующее правило.\n */\nconst abandonedLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.abandoned.length\n ? [\n `лежит от ресурсов, которые больше не берутся: ${result.abandoned.length}`,\n ...result.abandoned.map((path: string): string => ` ${path}`),\n ' их не стирает никто: рядом может лежать написанное проектом — убирать вручную',\n ]\n : [];\n\n/**\n * Ресурс, у которого нет вида под выбор дерева. Называется и то, чего не хватает, и оба способа\n * это снять: отказ без действия обходят, а не исполняют.\n */\nconst gapLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.gaps.flatMap((gap: IGapOfVariant): string[] => [\n ` ${gap.kind}/${gap.name} — есть только под ${gap.axis}: ${gap.available.join(', ')}, а выбран «${gap.chosen}»`,\n ` либо заведи вид под «${gap.chosen}», либо назови в skip: ${gap.ids.join(', ')}`,\n ]);\n\n/**\n * Гарды, которых нет в настройке агента, и готовый кусок для неё.\n *\n * Кусок печатается целиком, а не одними именами: правку в свою настройку делает проект, и\n * список «не хватает трёх» заставляет собирать JSON по памяти — там и теряется образец вызова.\n */\nconst unboundLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.unbound.length\n ? [\n `гарды разложены, но в \\`${SETTINGS_PATH}\\` их не зовёт никто: ${result.unbound.length}`,\n ...result.unbound.map((binding: IHookBinding): string => ` ${binding.path} — ${binding.event} ${binding.matcher}`),\n ` вставь в \\`${SETTINGS_PATH}\\` раздел \\`hooks\\` — готовый кусок ниже:`,\n ...JSON.stringify({ hooks: hooksSection(result.unbound) }, null, 4)\n .split('\\n')\n .map((line: string): string => ` ${line}`),\n ]\n : [];\n\nconst describe: (result: ISyncResult) => string[] = (result: ISyncResult): string[] => [\n ...holes(result),\n ...gapLines(result),\n ...unboundLines(result),\n ...pendingOf(result).map((entry: IPlanned): string => ` ${entry.path} — ${STATE_WORD[entry.outcome]}`),\n ...unfilled(result).map((entry: ICompanion): string => ` ${entry.path} — ${COMPANION_WORD[entry.state]}`),\n ...abandonedLines(result),\n];\n\n/** Имена дырок во всех ресурсах, которые дерево берёт. Без конфига — ни одной: выбор неизвестен. */\nfunction placeholdersIn(config: IConfig | null, assetsDir: string): readonly string[] {\n if (!config) {\n return [];\n }\n const names: string[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n for (const name of placeholdersOf(asset.text)) {\n if (!names.includes(name)) {\n names.push(name);\n }\n }\n }\n\n return names.sort();\n}\n\n/**\n * Что проект выбрал при заведении конфига. Пустой список — весь набор; выбор приходит сюда\n * готовым, потому что взять его негде, кроме края: у строки запуска флаг, у терминала вопрос,\n * а у неинтерактивного прогона нет ни того ни другого — и решать это команде не по чину.\n */\nexport function init(\n root: string,\n only: readonly string[] = [],\n variants: Readonly<Record<string, string>> = {},\n assetsDir: string = ''\n): IOutcomeOfCommand {\n const path: string = join(root, CONFIG_PATH);\n if (existsSync(path)) {\n return { code: 0, lines: [`${CONFIG_PATH} уже есть — оставлен как есть`] };\n }\n\n const config: object = { vars: {}, layout: DEFAULT_LAYOUT, variants, only, skip: [] };\n mkdirSync(join(root, OVERRIDES_DIR), { recursive: true });\n mkdirSync(join(root, CONFIG_PATH, '..'), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 4)}\\n`, 'utf8');\n\n // Значения, которых пакет ждёт от дерева, называются здесь, а не отказом раскладки: узнать\n // о них на первом же `sync` значит начать установку с ошибки, притом что список известен\n // сразу — он вычитывается из текстов выбранных ресурсов.\n const wanted: readonly string[] = assetsDir ? placeholdersIn(readConfig(root), assetsDir) : [];\n\n return {\n code: 0,\n lines: [\n `заведён ${CONFIG_PATH}`,\n only.length ? `выбрано ресурсов: ${only.length}` : 'выбрано всё, что везёт пакет',\n ...Object.entries(variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`),\n `заведён ${OVERRIDES_DIR}/ — надстройки проекта кладутся сюда путём ресурса`,\n ...(wanted.length\n ? [\n `значения, которых ждут ресурсы, — впиши их в \\`vars\\` конфига: ${wanted.length}`,\n ...wanted.map((name: string): string => ` {{${name}}}`),\n ]\n : []),\n 'дальше: `agent-kit sync`, а своё дописывается в `.claude/rt-kit/gate-map.sh` и `project.sh`',\n ],\n };\n}\n\n/**\n * Отказ на устаревшей сборке. Раскладка из неё положила бы прежнюю редакцию ресурса и назвала\n * это сделанным: неправда дороже отказа — её замечают, когда правленое правило не действует.\n */\nconst staleRefusal: (stale: IStaleBuild) => IOutcomeOfCommand = (stale: IStaleBuild): IOutcomeOfCommand => ({\n code: 1,\n lines: [\n 'раскладка не начата: строка запуска читает собранное, а ресурсы правлены позже',\n ` правлено: ${stale.newest}`,\n ` исходные ресурсы: ${stale.source}`,\n ' собери пакет и повтори',\n ],\n});\n\nexport function sync(env: IEnvironment, check: boolean): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n if (env.stale) {\n return staleRefusal(env.stale);\n }\n\n // Ось без ответа отбивает раскладку целиком, а не пропускает свои ресурсы молча: правило\n // поставки бывает в трёх видах, и дерево, не назвавшее свой, осталось бы вовсе без правила\n // поставки — заметить это можно было бы только по тому, что гейт перестал его требовать.\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n if (unanswered.length) {\n return { code: 1, lines: ['раскладка не начата: не выбран вид', ...axisLines(unanswered)] };\n }\n\n if (check) {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const pending: readonly IPlanned[] = pendingOf(result);\n // Незаполненный компаньон — такое же расхождение, как отставший файл: правило разложено,\n // а имён этого дерева при нём нет, и агент читает указание, которому некуда примениться.\n const empty: readonly ICompanion[] = unfilled(result);\n // Гард, которого не зовёт настройка агента, — такое же расхождение, как отставший файл:\n // он разложен, он коммитится, и по дереву его не отличить от работающего.\n const count: number = result.missing.size + result.gaps.length + pending.length + empty.length + result.unbound.length;\n if (!count) {\n return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`] };\n }\n\n return { code: 1, lines: [`sync --check: расхождений ${count}`, ...describe(result)] };\n }\n\n const result: ISyncResult = runSync(config, root, version, assetsDir);\n // Перечисляются только дырки: раскладка не начата, и назвать файл «положенным» значило бы\n // сказать неправду — на диске его нет.\n if (result.missing.size) {\n return { code: 1, lines: ['раскладка не начата: нечего подставить в дырки', ...holes(result)] };\n }\n\n // Ресурс без вида под выбор дерева отбивает раскладку целиком, а не выпадает из неё молча:\n // правило, разложенное без инструмента, который оно зовёт, читается как действующее.\n if (result.gaps.length) {\n return {\n code: 1,\n lines: ['раскладка не начата: у этих ресурсов нет вида под выбор дерева', ...gapLines(result)],\n };\n }\n\n const refused: readonly IPlanned[] = result.planned.filter((entry: IPlanned): boolean => isRefusal(entry.outcome));\n if (refused.length) {\n return {\n code: 1,\n lines: [\n 'раскладка не начата: эти файлы пакет переписывать не станет',\n ...refused.map((entry: IPlanned): string => ` ${entry.path} — ${DONE_WORD[entry.outcome]}`),\n 'правку надо либо перенести в надстройку, либо снять — и повторить',\n `положенное не пакетом отдаётся ему командой \\`agent-kit adopt\\`: прежнее содержимое ляжет рядом с пометкой \\`${KEPT_SUFFIX}\\``,\n ],\n };\n }\n\n // Раскладка удалась, а гарды могут остаться неподключёнными: настройка агента принадлежит\n // дереву, и пакет в неё не пишет. Код возврата остаётся нулевым — файлы легли, — но молчать\n // об этом нельзя: узнают иначе, когда что-нибудь пройдёт мимо гарда.\n return {\n code: 0,\n lines: [\n ...(result.written.length\n ? [`разложено файлов: ${result.written.length}`, ...result.written.map((path: string): string => ` ${path}`)]\n : ['всё уже разложено']),\n ...unboundLines(result),\n ],\n };\n}\n\n/**\n * Отдать пакету файл, который лежит в дереве не от него.\n *\n * Пока команды не было, `sync` отказывал на такой файл поимённо и предлагал «перенести правку в\n * надстройку или снять» — то есть работу, которую делают руками, и до неё же сводилась вся\n * установка в живое дерево. При этом один чужой файл останавливал раскладку целиком.\n *\n * Молчаливой перезаписи здесь нет и быть не может: в файле лежит то, чего в дереве больше нигде\n * нет. Поэтому переход — это переименование прежнего содержимого рядом и повторный `sync`:\n * пакет кладёт своё, а прежнее остаётся на диске под именем с пометкой и ждёт разбора.\n */\nexport function adopt(env: IEnvironment, names: readonly string[]): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const foreign: readonly IPlanned[] = planSync(config, root, version, assetsDir).planned.filter(\n (entry: IPlanned): boolean => entry.outcome === 'foreign'\n );\n if (!foreign.length) {\n return { code: 0, lines: ['чужих файлов на путях пакета нет'] };\n }\n\n // Имена принимаются как их печатает `sync`: путём в дереве. Без имён отдаются все — на\n // свежей установке их бывает столько же, сколько ресурсов, и перечислять их руками значит\n // делать ту же работу, ради которой команда заведена.\n const wanted: readonly IPlanned[] = names.length\n ? foreign.filter((entry: IPlanned): boolean => names.some((name: string): boolean => entry.path.endsWith(name)))\n : foreign;\n if (!wanted.length) {\n return {\n code: 1,\n lines: ['ни одно имя не отвечает чужому файлу; чужие сейчас такие:', ...foreign.map((e: IPlanned): string => ` ${e.path}`)],\n };\n }\n\n const moved: string[] = [];\n const blocked: string[] = [];\n for (const entry of wanted) {\n const path: string = join(root, entry.path);\n const kept: string = `${path}${KEPT_SUFFIX}`;\n if (existsSync(kept)) {\n blocked.push(` ${entry.path}${KEPT_SUFFIX} — уже лежит, разбери его прежде`);\n continue;\n }\n renameSync(path, kept);\n moved.push(` ${entry.path} → ${entry.path}${KEPT_SUFFIX}`);\n }\n\n return {\n code: blocked.length ? 1 : 0,\n lines: [\n ...(moved.length ? [`прежнее содержимое отложено: ${moved.length}`, ...moved, 'дальше: `agent-kit sync`'] : []),\n ...(blocked.length ? ['не тронуто:', ...blocked] : []),\n ],\n };\n}\n\nexport function doctor(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const counted: Map<TOutcome, number> = new Map();\n for (const entry of result.planned) {\n counted.set(entry.outcome, (counted.get(entry.outcome) ?? 0) + 1);\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const taken: number = collectAssets(config, assetsDir).length;\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n const chosen: string[] = Object.entries(config.variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`);\n // Ресурс чужого вида в «не выбрано» не идёт: проект от него не отказывался — его в этом\n // дереве не существует, как не существует второго правила поставки.\n const foreignVariant: readonly IEntryOfCatalog[] = catalog.filter(\n (entry: IEntryOfCatalog): boolean => entry.variant !== null && config.variants[entry.variant.axis] !== entry.variant.value\n );\n const other: number = foreignVariant.length;\n // Ресурс, названный и в отказе, и чужим видом, считается один раз — иначе «не выбрано»\n // уходит в минус, а минус в отчёте читается как поломка счёта, а не как двойной счёт.\n const skipped: number = config.skip.filter((id: string): boolean =>\n foreignVariant.every((entry: IEntryOfCatalog): boolean => entry.id !== id)\n ).length;\n\n const lines: string[] = [\n `пакет v${version}, везёт ресурсов ${catalog.length}, взято ${taken}`,\n `не выбрано: ${catalog.length - taken - skipped - other}, пропущено: ${skipped}, другой вид: ${other}`,\n `значений в конфиге: ${Object.keys(config.vars).length}`,\n ...chosen,\n ...[...counted].map(([outcome, count]: [TOutcome, number]): string => `${STATE_WORD[outcome]}: ${count}`),\n ...describe(result),\n ...(unanswered.length ? ['не выбран вид — раскладка не начнётся:', ...axisLines(unanswered)] : []),\n // Про устаревшую сборку `doctor` говорит, но отказом её не считает: он ничего не пишет,\n // и прочитать состояние дерева можно и из вчерашней сборки — знать бы, что она вчерашняя.\n ...(env.stale ? ['собранное отстало от исходников — раскладка откажет:', ` правлено: ${env.stale.newest}`] : []),\n ];\n\n return { code: 0, lines };\n}\n\n/**\n * Что пакет везёт и что из этого взято здесь.\n *\n * Работает и без конфига: посмотреть, из чего выбирать, нужно раньше, чем выбор сделан, — иначе\n * имена законов взять неоткуда, кроме исходников пакета.\n */\nexport function list(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const planned: Map<string, TOutcome> = new Map();\n\n if (config) {\n for (const entry of planSync(config, root, version, assetsDir).planned) {\n planned.set(entry.asset, entry.outcome);\n }\n }\n\n const stateOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => {\n if (!config) {\n return 'везёт пакет';\n }\n if (entry.variant && config.variants[entry.variant.axis] !== entry.variant.value) {\n return OTHER_VARIANT;\n }\n if (config.skip.includes(entry.id)) {\n return SKIPPED;\n }\n if (!isChosen(entry, config)) {\n return NOT_CHOSEN;\n }\n const outcome: TOutcome | undefined = planned.get(entry.id);\n\n // Ресурса нет среди запланированных ровно в одном случае: в нём осталась дырка без\n // значения, и до решения о судьбе файла раскладка не дошла.\n return outcome ? STATE_WORD[outcome] : 'дырка без значения';\n };\n\n const name: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, entry.name.length), 0);\n const state: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, stateOf(entry).length), 0);\n const lines: string[] = [config ? `пакет v${version}` : `пакет v${version}, ${CONFIG_PATH} ещё не заведён`];\n\n for (const kind of KINDS) {\n const entries: readonly IEntryOfCatalog[] = catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind);\n if (!entries.length) {\n continue;\n }\n lines.push('', KIND_TITLE[kind]);\n lines.push(\n ...entries.map(\n (entry: IEntryOfCatalog): string => ` ${entry.name.padEnd(name)} ${stateOf(entry).padEnd(state)} ${entry.title}`\n )\n );\n }\n\n return { code: 0, lines };\n}\n"]}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Команды и их вывод. Печать отделена от работы: команда возвращает строки и код возврата,\n * а `process.exit` зовёт только точка входа — иначе ни одну из них нельзя было бы проверить\n * спекой, не перехватывая поток вывода.\n */\nimport { existsSync, mkdirSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { collectAssets } from './assets.js';\nimport { IEntryOfCatalog, IGapOfVariant, isChosen, readCatalog } from './catalog.js';\nimport { ICompanion, isUnfilled, TCompanionState } from './companion.js';\nimport { CONFIG_PATH, DEFAULT_LAYOUT, IConfig, KINDS, OVERRIDES_DIR, readConfig, TKind } from './config.js';\nimport { IStaleBuild } from './freshness.js';\nimport { hooksSection, IHookBinding, SETTINGS_PATH } from './hooks-map.js';\nimport { IPlanned, isRefusal, TOutcome } from './plan.js';\nimport { ISyncResult, pendingOf, planSync, runSync } from './sync.js';\nimport { placeholdersOf } from './vars.js';\nimport { IAxis, IOptionOfAxis, readAxes, unansweredAxes } from './variants.js';\n\nexport interface IOutcomeOfCommand {\n readonly code: number;\n readonly lines: readonly string[];\n}\n\n/** Всё, что команда знает о мире: корень проекта, версия пакета и его каталог ресурсов. */\nexport interface IEnvironment {\n readonly root: string;\n readonly version: string;\n readonly assetsDir: string;\n /**\n * Ресурсы правлены позже, чем собран пакет, из которого идёт раскладка; `null` — сверять не с\n * чем. Считается на краю, где пакет знает своё расположение: библиотечные модули работают с\n * тем каталогом ресурсов, который им дали, и о существовании исходников не знают.\n */\n readonly stale?: IStaleBuild | null;\n}\n\n/** Что с файлом сделала раскладка. Прошедшее время здесь правда: `sync` уже записал. */\nconst DONE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'положен',\n update: 'переложен',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'без изменений',\n};\n\n/**\n * Что с файлом **сейчас**. Отдельно от прошедшего времени потому, что `doctor` и `list` ничего\n * не пишут: сказать «положен» о файле, которого в дереве нет, значит соврать читателю ровно там,\n * где он пришёл узнать состояние.\n */\nconst STATE_WORD: Readonly<Record<TOutcome, string>> = {\n create: 'нет в дереве',\n update: 'отстал от пакета',\n drift: 'правлен руками',\n foreign: 'положен не пакетом',\n ok: 'на месте',\n};\n\nconst NOT_CHOSEN: string = 'не выбран';\nconst SKIPPED: string = 'пропущен';\n/** Ресурс чужого вида: в этом дереве его не существует, а не «от него отказались». */\nconst OTHER_VARIANT: string = 'другой вид';\n\nconst KIND_TITLE: Readonly<Record<TKind, string>> = {\n laws: 'ЗАКОНЫ',\n rules: 'ПРАВИЛА',\n patterns: 'ПАТТЕРНЫ',\n skills: 'СКИЛЫ',\n hooks: 'ХУКИ',\n defaults: 'УМОЛЧАНИЯ',\n checks: 'ПРОВЕРКИ',\n agents: 'АГЕНТЫ',\n commands: 'КОМАНДЫ',\n workflows: 'ВОРКФЛОУ',\n templates: 'ШАБЛОНЫ',\n docs: 'ДОКУМЕНТЫ',\n};\n\n/** Состояние компаньона словами. У заполненного слова нет: о нём говорить нечего. */\nconst COMPANION_WORD: Readonly<Record<TCompanionState, string>> = {\n missing: 'пропал',\n draft: 'остался черновиком',\n filled: 'заполнен',\n};\n\nconst NO_CONFIG: string = `нет \\`${CONFIG_PATH}\\` — начни с \\`agent-kit init\\``;\n\n/** Куда уезжает прежнее содержимое файла, отданного пакету. */\nexport const KEPT_SUFFIX: string = '.before-rt-kit';\n\nconst holes: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n [...result.missing].map(\n ([asset, names]: [string, readonly string[]]): string =>\n ` ${asset}: нет значений для ${names.map((name: string): string => `{{${name}}}`).join(', ')}`\n );\n\nconst unfilled: (result: ISyncResult) => readonly ICompanion[] = (result: ISyncResult): readonly ICompanion[] =>\n result.companions.filter(isUnfilled);\n\n/** Ось без ответа: чем её спрашивают и из чего выбирают. */\nconst axisLines: (axes: readonly IAxis[]) => string[] = (axes: readonly IAxis[]): string[] =>\n axes.flatMap((axis: IAxis): string[] => [\n ` ${axis.name} — ${axis.question}`,\n ...axis.options.map((option: IOptionOfAxis): string => ` ${option.value.padEnd(8)} ${option.title}`),\n ` выбор пишется в \\`variants\\` конфига: {\"${axis.name}\": \"${axis.options[0]?.value ?? ''}\"}`,\n ]);\n\n/**\n * Брошенное: файл лежит, а ресурс за ним больше не берут. Печатается отдельным списком и с\n * подсказкой — стереть его пакет не вправе, а промолчать не может: агент читает такой файл как\n * действующее правило.\n */\nconst abandonedLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.abandoned.length\n ? [\n `лежит от ресурсов, которые больше не берутся: ${result.abandoned.length}`,\n ...result.abandoned.map((path: string): string => ` ${path}`),\n ' их не стирает никто: рядом может лежать написанное проектом — убирать вручную',\n ]\n : [];\n\n/**\n * Ресурс, у которого нет вида под выбор дерева. Называется и то, чего не хватает, и оба способа\n * это снять: отказ без действия обходят, а не исполняют.\n */\nconst gapLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.gaps.flatMap((gap: IGapOfVariant): string[] => [\n ` ${gap.kind}/${gap.name} — есть только под ${gap.axis}: ${gap.available.join(', ')}, а выбран «${gap.chosen}»`,\n ` либо заведи вид под «${gap.chosen}», либо назови в skip: ${gap.ids.join(', ')}`,\n ]);\n\n/**\n * Гарды, которых нет в настройке агента, и готовый кусок для неё.\n *\n * Кусок печатается целиком, а не одними именами: правку в свою настройку делает проект, и\n * список «не хватает трёх» заставляет собирать JSON по памяти — там и теряется образец вызова.\n */\nconst unboundLines: (result: ISyncResult) => string[] = (result: ISyncResult): string[] =>\n result.unbound.length\n ? [\n `гарды разложены, но в \\`${SETTINGS_PATH}\\` их не зовёт никто: ${result.unbound.length}`,\n ...result.unbound.map(\n (binding: IHookBinding): string => ` ${binding.path} — ${binding.event}${binding.matcher ? ` ${binding.matcher}` : ''}`\n ),\n ` вставь в \\`${SETTINGS_PATH}\\` раздел \\`hooks\\` — готовый кусок ниже:`,\n ...JSON.stringify({ hooks: hooksSection(result.unbound) }, null, 4)\n .split('\\n')\n .map((line: string): string => ` ${line}`),\n ]\n : [];\n\nconst describe: (result: ISyncResult) => string[] = (result: ISyncResult): string[] => [\n ...holes(result),\n ...gapLines(result),\n ...unboundLines(result),\n ...pendingOf(result).map((entry: IPlanned): string => ` ${entry.path} — ${STATE_WORD[entry.outcome]}`),\n ...unfilled(result).map((entry: ICompanion): string => ` ${entry.path} — ${COMPANION_WORD[entry.state]}`),\n ...abandonedLines(result),\n];\n\n/** Имена дырок во всех ресурсах, которые дерево берёт. Без конфига — ни одной: выбор неизвестен. */\nfunction placeholdersIn(config: IConfig | null, assetsDir: string): readonly string[] {\n if (!config) {\n return [];\n }\n const names: string[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n for (const name of placeholdersOf(asset.text)) {\n if (!names.includes(name)) {\n names.push(name);\n }\n }\n }\n\n return names.sort();\n}\n\n/**\n * Что проект выбрал при заведении конфига. Пустой список — весь набор; выбор приходит сюда\n * готовым, потому что взять его негде, кроме края: у строки запуска флаг, у терминала вопрос,\n * а у неинтерактивного прогона нет ни того ни другого — и решать это команде не по чину.\n */\nexport function init(\n root: string,\n only: readonly string[] = [],\n variants: Readonly<Record<string, string>> = {},\n assetsDir: string = ''\n): IOutcomeOfCommand {\n const path: string = join(root, CONFIG_PATH);\n if (existsSync(path)) {\n return { code: 0, lines: [`${CONFIG_PATH} уже есть — оставлен как есть`] };\n }\n\n const config: object = { vars: {}, layout: DEFAULT_LAYOUT, variants, only, skip: [] };\n mkdirSync(join(root, OVERRIDES_DIR), { recursive: true });\n mkdirSync(join(root, CONFIG_PATH, '..'), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 4)}\\n`, 'utf8');\n\n // Значения, которых пакет ждёт от дерева, называются здесь, а не отказом раскладки: узнать\n // о них на первом же `sync` значит начать установку с ошибки, притом что список известен\n // сразу — он вычитывается из текстов выбранных ресурсов.\n const wanted: readonly string[] = assetsDir ? placeholdersIn(readConfig(root), assetsDir) : [];\n\n return {\n code: 0,\n lines: [\n `заведён ${CONFIG_PATH}`,\n only.length ? `выбрано ресурсов: ${only.length}` : 'выбрано всё, что везёт пакет',\n ...Object.entries(variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`),\n `заведён ${OVERRIDES_DIR}/ — надстройки проекта кладутся сюда путём ресурса`,\n ...(wanted.length\n ? [\n `значения, которых ждут ресурсы, — впиши их в \\`vars\\` конфига: ${wanted.length}`,\n ...wanted.map((name: string): string => ` {{${name}}}`),\n ]\n : []),\n 'дальше: `agent-kit sync`, а своё дописывается в `.claude/rt-kit/gate-map.sh` и `project.sh`',\n ],\n };\n}\n\n/**\n * Отказ на устаревшей сборке. Раскладка из неё положила бы прежнюю редакцию ресурса и назвала\n * это сделанным: неправда дороже отказа — её замечают, когда правленое правило не действует.\n */\nconst staleRefusal: (stale: IStaleBuild) => IOutcomeOfCommand = (stale: IStaleBuild): IOutcomeOfCommand => ({\n code: 1,\n lines: [\n 'раскладка не начата: строка запуска читает собранное, а ресурсы правлены позже',\n ` правлено: ${stale.newest}`,\n ` исходные ресурсы: ${stale.source}`,\n ' собери пакет и повтори',\n ],\n});\n\nexport function sync(env: IEnvironment, check: boolean): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n if (env.stale) {\n return staleRefusal(env.stale);\n }\n\n // Ось без ответа отбивает раскладку целиком, а не пропускает свои ресурсы молча: правило\n // поставки бывает в трёх видах, и дерево, не назвавшее свой, осталось бы вовсе без правила\n // поставки — заметить это можно было бы только по тому, что гейт перестал его требовать.\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n if (unanswered.length) {\n return { code: 1, lines: ['раскладка не начата: не выбран вид', ...axisLines(unanswered)] };\n }\n\n if (check) {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const pending: readonly IPlanned[] = pendingOf(result);\n // Незаполненный компаньон — такое же расхождение, как отставший файл: правило разложено,\n // а имён этого дерева при нём нет, и агент читает указание, которому некуда примениться.\n const empty: readonly ICompanion[] = unfilled(result);\n // Гард, которого не зовёт настройка агента, — такое же расхождение, как отставший файл:\n // он разложен, он коммитится, и по дереву его не отличить от работающего.\n const count: number = result.missing.size + result.gaps.length + pending.length + empty.length + result.unbound.length;\n if (!count) {\n return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`] };\n }\n\n return { code: 1, lines: [`sync --check: расхождений ${count}`, ...describe(result)] };\n }\n\n const result: ISyncResult = runSync(config, root, version, assetsDir);\n // Перечисляются только дырки: раскладка не начата, и назвать файл «положенным» значило бы\n // сказать неправду — на диске его нет.\n if (result.missing.size) {\n return { code: 1, lines: ['раскладка не начата: нечего подставить в дырки', ...holes(result)] };\n }\n\n // Ресурс без вида под выбор дерева отбивает раскладку целиком, а не выпадает из неё молча:\n // правило, разложенное без инструмента, который оно зовёт, читается как действующее.\n if (result.gaps.length) {\n return {\n code: 1,\n lines: ['раскладка не начата: у этих ресурсов нет вида под выбор дерева', ...gapLines(result)],\n };\n }\n\n const refused: readonly IPlanned[] = result.planned.filter((entry: IPlanned): boolean => isRefusal(entry.outcome));\n if (refused.length) {\n return {\n code: 1,\n lines: [\n 'раскладка не начата: эти файлы пакет переписывать не станет',\n ...refused.map((entry: IPlanned): string => ` ${entry.path} — ${DONE_WORD[entry.outcome]}`),\n 'правку надо либо перенести в надстройку, либо снять — и повторить',\n `положенное не пакетом отдаётся ему командой \\`agent-kit adopt\\`: прежнее содержимое ляжет рядом с пометкой \\`${KEPT_SUFFIX}\\``,\n ],\n };\n }\n\n // Раскладка удалась, а гарды могут остаться неподключёнными: настройка агента принадлежит\n // дереву, и пакет в неё не пишет. Код возврата остаётся нулевым — файлы легли, — но молчать\n // об этом нельзя: узнают иначе, когда что-нибудь пройдёт мимо гарда.\n return {\n code: 0,\n lines: [\n ...(result.written.length\n ? [`разложено файлов: ${result.written.length}`, ...result.written.map((path: string): string => ` ${path}`)]\n : ['всё уже разложено']),\n ...unboundLines(result),\n ],\n };\n}\n\n/**\n * Отдать пакету файл, который лежит в дереве не от него.\n *\n * Пока команды не было, `sync` отказывал на такой файл поимённо и предлагал «перенести правку в\n * надстройку или снять» — то есть работу, которую делают руками, и до неё же сводилась вся\n * установка в живое дерево. При этом один чужой файл останавливал раскладку целиком.\n *\n * Молчаливой перезаписи здесь нет и быть не может: в файле лежит то, чего в дереве больше нигде\n * нет. Поэтому переход — это переименование прежнего содержимого рядом и повторный `sync`:\n * пакет кладёт своё, а прежнее остаётся на диске под именем с пометкой и ждёт разбора.\n */\nexport function adopt(env: IEnvironment, names: readonly string[]): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const foreign: readonly IPlanned[] = planSync(config, root, version, assetsDir).planned.filter(\n (entry: IPlanned): boolean => entry.outcome === 'foreign'\n );\n if (!foreign.length) {\n return { code: 0, lines: ['чужих файлов на путях пакета нет'] };\n }\n\n // Имена принимаются как их печатает `sync`: путём в дереве. Без имён отдаются все — на\n // свежей установке их бывает столько же, сколько ресурсов, и перечислять их руками значит\n // делать ту же работу, ради которой команда заведена.\n const wanted: readonly IPlanned[] = names.length\n ? foreign.filter((entry: IPlanned): boolean => names.some((name: string): boolean => entry.path.endsWith(name)))\n : foreign;\n if (!wanted.length) {\n return {\n code: 1,\n lines: ['ни одно имя не отвечает чужому файлу; чужие сейчас такие:', ...foreign.map((e: IPlanned): string => ` ${e.path}`)],\n };\n }\n\n const moved: string[] = [];\n const blocked: string[] = [];\n for (const entry of wanted) {\n const path: string = join(root, entry.path);\n const kept: string = `${path}${KEPT_SUFFIX}`;\n if (existsSync(kept)) {\n blocked.push(` ${entry.path}${KEPT_SUFFIX} — уже лежит, разбери его прежде`);\n continue;\n }\n renameSync(path, kept);\n moved.push(` ${entry.path} → ${entry.path}${KEPT_SUFFIX}`);\n }\n\n return {\n code: blocked.length ? 1 : 0,\n lines: [\n ...(moved.length ? [`прежнее содержимое отложено: ${moved.length}`, ...moved, 'дальше: `agent-kit sync`'] : []),\n ...(blocked.length ? ['не тронуто:', ...blocked] : []),\n ],\n };\n}\n\nexport function doctor(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n if (!config) {\n return { code: 1, lines: [NO_CONFIG] };\n }\n\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n const counted: Map<TOutcome, number> = new Map();\n for (const entry of result.planned) {\n counted.set(entry.outcome, (counted.get(entry.outcome) ?? 0) + 1);\n }\n\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const taken: number = collectAssets(config, assetsDir).length;\n const unanswered: readonly IAxis[] = unansweredAxes(readAxes(assetsDir), config.variants);\n const chosen: string[] = Object.entries(config.variants).map(([axis, value]: [string, string]): string => `${axis}: ${value}`);\n // Ресурс чужого вида в «не выбрано» не идёт: проект от него не отказывался — его в этом\n // дереве не существует, как не существует второго правила поставки.\n const foreignVariant: readonly IEntryOfCatalog[] = catalog.filter(\n (entry: IEntryOfCatalog): boolean => entry.variant !== null && config.variants[entry.variant.axis] !== entry.variant.value\n );\n const other: number = foreignVariant.length;\n // Ресурс, названный и в отказе, и чужим видом, считается один раз — иначе «не выбрано»\n // уходит в минус, а минус в отчёте читается как поломка счёта, а не как двойной счёт.\n const skipped: number = config.skip.filter((id: string): boolean =>\n foreignVariant.every((entry: IEntryOfCatalog): boolean => entry.id !== id)\n ).length;\n\n const lines: string[] = [\n `пакет v${version}, везёт ресурсов ${catalog.length}, взято ${taken}`,\n `не выбрано: ${catalog.length - taken - skipped - other}, пропущено: ${skipped}, другой вид: ${other}`,\n `значений в конфиге: ${Object.keys(config.vars).length}`,\n ...chosen,\n ...[...counted].map(([outcome, count]: [TOutcome, number]): string => `${STATE_WORD[outcome]}: ${count}`),\n ...describe(result),\n ...(unanswered.length ? ['не выбран вид — раскладка не начнётся:', ...axisLines(unanswered)] : []),\n // Про устаревшую сборку `doctor` говорит, но отказом её не считает: он ничего не пишет,\n // и прочитать состояние дерева можно и из вчерашней сборки — знать бы, что она вчерашняя.\n ...(env.stale ? ['собранное отстало от исходников — раскладка откажет:', ` правлено: ${env.stale.newest}`] : []),\n ];\n\n return { code: 0, lines };\n}\n\n/**\n * Что пакет везёт и что из этого взято здесь.\n *\n * Работает и без конфига: посмотреть, из чего выбирать, нужно раньше, чем выбор сделан, — иначе\n * имена законов взять неоткуда, кроме исходников пакета.\n */\nexport function list(env: IEnvironment): IOutcomeOfCommand {\n const { root, version, assetsDir } = env;\n const config: IConfig | null = readConfig(root);\n const catalog: readonly IEntryOfCatalog[] = readCatalog(assetsDir);\n const planned: Map<string, TOutcome> = new Map();\n\n if (config) {\n for (const entry of planSync(config, root, version, assetsDir).planned) {\n planned.set(entry.asset, entry.outcome);\n }\n }\n\n const stateOf: (entry: IEntryOfCatalog) => string = (entry: IEntryOfCatalog): string => {\n if (!config) {\n return 'везёт пакет';\n }\n if (entry.variant && config.variants[entry.variant.axis] !== entry.variant.value) {\n return OTHER_VARIANT;\n }\n if (config.skip.includes(entry.id)) {\n return SKIPPED;\n }\n if (!isChosen(entry, config)) {\n return NOT_CHOSEN;\n }\n const outcome: TOutcome | undefined = planned.get(entry.id);\n\n // Ресурса нет среди запланированных ровно в одном случае: в нём осталась дырка без\n // значения, и до решения о судьбе файла раскладка не дошла.\n return outcome ? STATE_WORD[outcome] : 'дырка без значения';\n };\n\n const name: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, entry.name.length), 0);\n const state: number = catalog.reduce((found: number, entry: IEntryOfCatalog): number => Math.max(found, stateOf(entry).length), 0);\n const lines: string[] = [config ? `пакет v${version}` : `пакет v${version}, ${CONFIG_PATH} ещё не заведён`];\n\n for (const kind of KINDS) {\n const entries: readonly IEntryOfCatalog[] = catalog.filter((entry: IEntryOfCatalog): boolean => entry.kind === kind);\n if (!entries.length) {\n continue;\n }\n lines.push('', KIND_TITLE[kind]);\n lines.push(\n ...entries.map(\n (entry: IEntryOfCatalog): string => ` ${entry.name.padEnd(name)} ${stateOf(entry).padEnd(state)} ${entry.title}`\n )\n );\n }\n\n return { code: 0, lines };\n}\n"]}
package/lib/config.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  /** Род ресурса. Он же имя каталога в `assets/` пакета и ключ раскладки. */
2
- export type TKind = 'laws' | 'rules' | 'patterns' | 'skills' | 'hooks' | 'defaults' | 'checks' | 'agents' | 'commands' | 'workflows' | 'templates';
2
+ export type TKind = 'laws' | 'rules' | 'patterns' | 'skills' | 'hooks' | 'defaults' | 'checks' | 'agents' | 'commands' | 'workflows' | 'templates'
3
+ /** Документы дерева, которые читает и человек, и агент: словарь проекта. */
4
+ | 'docs';
3
5
  export declare const KINDS: readonly TKind[];
4
6
  /**
5
7
  * Роды, которые ложатся не файлом в каталог, а каталогом по имени ресурса: скил читается как
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/config.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,MAAM,MAAM,KAAK,GACb,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAEnI,eAAO,MAAM,KAAK,EAAE,SAAS,KAAK,EAYjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,KAAK,EAAoC,CAAC;AAE7E,iFAAiF;AACjF,eAAO,MAAM,UAAU,EAAE,MAAmB,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAA4B,CAAC;AAE1D,MAAM,WAAW,OAAO;IACpB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,WAAW,EAAE,MAA8B,CAAC;AACzD,eAAO,MAAM,aAAa,EAAE,MAAmC,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,EAAE,MAAkC,CAAC;AAC9D,eAAO,MAAM,aAAa,EAAE,MAAsB,CAAC;AACnD,eAAO,MAAM,YAAY,EAAE,MAAqB,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAY1D,CAAC;AAEF,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAgCzC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmCjD;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAUvD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/config.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,MAAM,MAAM,KAAK,GACX,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,OAAO,GACP,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,WAAW,GACX,WAAW;AACb,4EAA4E;GAC1E,MAAM,CAAC;AAEb,eAAO,MAAM,KAAK,EAAE,SAAS,KAAK,EAajC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,KAAK,EAAoC,CAAC;AAE7E,iFAAiF;AACjF,eAAO,MAAM,UAAU,EAAE,MAAmB,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAA4B,CAAC;AAE1D,MAAM,WAAW,OAAO;IACpB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,WAAW,EAAE,MAA8B,CAAC;AACzD,eAAO,MAAM,aAAa,EAAE,MAAmC,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,EAAE,MAAkC,CAAC;AAC9D,eAAO,MAAM,aAAa,EAAE,MAAsB,CAAC;AACnD,eAAO,MAAM,YAAY,EAAE,MAAqB,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAa1D,CAAC;AAEF,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAgCzC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmCjD;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAUvD"}
package/lib/config.js CHANGED
@@ -19,6 +19,7 @@ export const KINDS = [
19
19
  'commands',
20
20
  'workflows',
21
21
  'templates',
22
+ 'docs',
22
23
  ];
23
24
  /**
24
25
  * Роды, которые ложатся не файлом в каталог, а каталогом по имени ресурса: скил читается как
@@ -73,6 +74,7 @@ export const DEFAULT_LAYOUT = {
73
74
  commands: '.claude/commands',
74
75
  workflows: '.claude/workflows',
75
76
  templates: '.claude/rt-kit/templates',
77
+ docs: 'docs',
76
78
  };
77
79
  export class ConfigError extends Error {
78
80
  }
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,MAAM,CAAC,MAAM,KAAK,GAAqB;IACnC,MAAM;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,OAAO;IACP,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,WAAW;IACX,WAAW;CACd,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE7E,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAW,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAW,mBAAmB,CAAC;AAsB1D,MAAM,CAAC,MAAM,WAAW,GAAW,qBAAqB,CAAC;AACzD,MAAM,CAAC,MAAM,aAAa,GAAW,0BAA0B,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GAAW,yBAAyB,CAAC;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAW,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,YAAY,GAAW,YAAY,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAoC;IAC3D,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,gBAAgB;IACvB,QAAQ,EAAE,gBAAgB;IAC1B,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE,eAAe;IACtB,QAAQ,EAAE,YAAY;IACtB,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,gBAAgB;IACxB,QAAQ,EAAE,kBAAkB;IAC5B,SAAS,EAAE,mBAAmB;IAC9B,SAAS,EAAE,0BAA0B;CACxC,CAAC;AAEF,MAAM,OAAO,WAAY,SAAQ,KAAK;CAAG;AAEzC,MAAM,QAAQ,GAAyD,CAAC,KAAc,EAAoC,EAAE,CACxH,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEzE,SAAS,SAAS,CAAC,KAAc,EAAE,KAAa;IAC5C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,WAAW,CAAC,GAAG,KAAK,qCAAqC,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,WAAW,CAAC,GAAG,KAAK,IAAI,GAAG,oBAAoB,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,MAAM,CAAC,KAAc,EAAE,KAAa;IACzC,MAAM,IAAI,GAAY,KAAK,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,KAAc,EAAW,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,WAAW,CAAC,GAAG,KAAK,6CAA6C,CAAC,CAAC;IACjF,CAAC;IAED,OAAO,IAAgB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACpC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACD,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACtB,MAAM,IAAI,WAAW,CAAC,GAAG,WAAW,+BAAgC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,WAAW,CAAC,GAAG,WAAW,oBAAoB,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,GAAG,cAAc,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;IACpG,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAa,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,WAAW,CAAC,UAAU,IAAI,qCAAqC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAsB,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAsB,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAE5D,4FAA4F;IAC5F,8EAA8E;IAC9E,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACH,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE;QACvD,MAAM,EAAE,MAA+B;QACvC,IAAI;QACJ,IAAI;QACJ,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;KACnD,CAAC;AACN,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,UAAU,CAAC,IAAY;IACnC,IAAI,CAAC;QACD,OAAO,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACtB,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YAC/B,MAAM,KAAK,CAAC;QAChB,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC","sourcesContent":["/**\n * Конфиг проекта — `.claude/rt-kit.json`.\n *\n * Всё, что пакет не может знать сам: значения для дырок, куда класть каждый род ресурса и от\n * чего проект отказался. Конфиг лежит в дереве проекта и коммитится: раскладка обязана\n * повторяться на чужой машине без вопросов, иначе разложенное расходится между разработчиками.\n */\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Род ресурса. Он же имя каталога в `assets/` пакета и ключ раскладки. */\nexport type TKind =\n 'laws' | 'rules' | 'patterns' | 'skills' | 'hooks' | 'defaults' | 'checks' | 'agents' | 'commands' | 'workflows' | 'templates';\n\nexport const KINDS: readonly TKind[] = [\n 'laws',\n 'rules',\n 'patterns',\n 'skills',\n 'hooks',\n 'defaults',\n 'checks',\n 'agents',\n 'commands',\n 'workflows',\n 'templates',\n];\n\n/**\n * Роды, которые ложатся не файлом в каталог, а каталогом по имени ресурса: скил читается как\n * `<имя>/SKILL.md`, и рядом с ним лежит то, что пишет проект.\n *\n * `skills` — скил, у которого нет закона над собой: он не про то, что должно быть верно в\n * продукте, а про то, как здесь делается работа. Правилом его называть нельзя — тогда придётся\n * выдумать ему закон, — а паттерном тем более: паттерн стоит при правиле.\n */\nexport const SKILL_KINDS: readonly TKind[] = ['rules', 'patterns', 'skills'];\n\n/** Имя файла скила: так его ищет агент, и другого имени у него быть не может. */\nexport const SKILL_FILE: string = 'SKILL.md';\n\n/**\n * Файл-компаньон правила: чем названо в этом дереве то, о чём правило говорит приёмом.\n *\n * Пакет знает приём, но не знает ни путей, ни имён — их пишет проект. Черновик кладётся один\n * раз и дальше не сверяется: это единственный файл раскладки, который принадлежит проекту.\n */\nexport const COMPANION_FILE: string = 'implementation.md';\n\nexport interface IConfig {\n /** Значения дырок `{{имя}}`. */\n readonly vars: Readonly<Record<string, string>>;\n /** Куда класть каждый род ресурса, путями от корня проекта. */\n readonly layout: Readonly<Record<TKind, string>>;\n /**\n * Ресурсы, которые проект выбрал, идентификаторами: `laws/access.md`. Пусто — берётся всё.\n * Ограничивает только те роды, которые сам называет; как именно — `isChosen`.\n */\n readonly only: readonly string[];\n /** Ресурсы, от которых проект отказался, идентификаторами: `laws/application/money.md`. */\n readonly skip: readonly string[];\n /**\n * Выбор проекта по осям различия: `{ \"host\": \"gitlab\" }`. Оси объявлены пакетом в\n * `assets/variants.json`, а ресурс с вариантом в имени берётся, только если проект выбрал\n * его значение; как именно — `isChosen`.\n */\n readonly variants: Readonly<Record<string, string>>;\n}\n\nexport const CONFIG_PATH: string = '.claude/rt-kit.json';\nexport const OVERRIDES_DIR: string = '.claude/rt-kit/overrides';\n\n/**\n * Карта «что правится — какое правило» и профиль дерева: команды, стенды, пары «правка —\n * документ». Оба лежат в двух видах, и это не дублирование, а разделение ответственности.\n *\n * Умолчание везёт пакет: проекты этой мастерской устроены одинаково — Nx, те же расширения, те\n * же имена каталогов, — и переписывать одну и ту же карту в каждом дереве заново значило бы\n * заводить пятнадцать её редакций, расходящихся молча. Оно разложено, под шапкой, и правится\n * не на месте.\n *\n * Надстройку пишет проект, и она необязательна: витрина, свой род файлов, другой запускатель\n * тестов есть не у всех. Объявленная в ней функция замещает умолчание целиком и вправе позвать\n * его обратно суффиксом `_default` — так дерево дописывает своё, не теряя общего.\n */\nexport const DEFAULTS_DIR: string = '.claude/rt-kit/defaults';\nexport const GATE_MAP_FILE: string = 'gate-map.sh';\nexport const PROFILE_FILE: string = 'project.sh';\n\n/**\n * Умолчания раскладки. Это не единственно возможные пути, но менять их без нужды не стоит:\n * агент ищет законы в `docs/constitution`, потому что так написано в правилах, которые пакет\n * же и везёт.\n */\nexport const DEFAULT_LAYOUT: Readonly<Record<TKind, string>> = {\n laws: 'docs/constitution',\n rules: '.claude/skills',\n patterns: '.claude/skills',\n skills: '.claude/skills',\n hooks: '.claude/hooks',\n defaults: DEFAULTS_DIR,\n checks: 'tools',\n agents: '.claude/agents',\n commands: '.claude/commands',\n workflows: '.claude/workflows',\n templates: '.claude/rt-kit/templates',\n};\n\nexport class ConfigError extends Error {}\n\nconst isRecord: (value: unknown) => value is Record<string, unknown> = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nfunction stringMap(value: unknown, where: string): Record<string, string> {\n if (value === undefined) {\n return {};\n }\n if (!isRecord(value)) {\n throw new ConfigError(`${where}: ожидается объект «имя — значение»`);\n }\n const result: Record<string, string> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (typeof entry !== 'string') {\n throw new ConfigError(`${where}.${key}: ожидается строка`);\n }\n result[key] = entry;\n }\n\n return result;\n}\n\nfunction idList(value: unknown, where: string): readonly string[] {\n const list: unknown = value ?? [];\n if (!Array.isArray(list) || list.some((entry: unknown): boolean => typeof entry !== 'string')) {\n throw new ConfigError(`${where}: ожидается список идентификаторов ресурсов`);\n }\n\n return list as string[];\n}\n\nexport function parseConfig(text: string): IConfig {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (error: unknown) {\n throw new ConfigError(`${CONFIG_PATH} — не разбирается как JSON: ${(error as Error).message}`);\n }\n if (!isRecord(raw)) {\n throw new ConfigError(`${CONFIG_PATH}: ожидается объект`);\n }\n\n const layout: Record<string, string> = { ...DEFAULT_LAYOUT, ...stringMap(raw['layout'], 'layout') };\n for (const kind of Object.keys(layout)) {\n if (!KINDS.includes(kind as TKind)) {\n throw new ConfigError(`layout.${kind}: такого рода ресурсов нет — есть ${KINDS.join(', ')}`);\n }\n }\n\n const only: readonly string[] = idList(raw['only'], 'only');\n const skip: readonly string[] = idList(raw['skip'], 'skip');\n\n // Пути раскладки — тоже значения проекта, и пакет их уже знает. Требовать их вторым списком\n // значило бы держать одно и то же в двух местах: расходятся такие пары молча.\n const derived: Record<string, string> = {};\n for (const kind of KINDS) {\n derived[`${kind.replace(/s$/, '')}sDir`] = layout[kind];\n }\n\n return {\n vars: { ...derived, ...stringMap(raw['vars'], 'vars') },\n layout: layout as Record<TKind, string>,\n only,\n skip,\n variants: stringMap(raw['variants'], 'variants'),\n };\n}\n\n/** Конфиг проекта; его отсутствие — не отказ, а повод сказать про `agent-kit init`. */\nexport function readConfig(root: string): IConfig | null {\n try {\n return parseConfig(readFileSync(join(root, CONFIG_PATH), 'utf8'));\n } catch (error: unknown) {\n if (error instanceof ConfigError) {\n throw error;\n }\n\n return null;\n }\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Конфиг проекта — `.claude/rt-kit.json`.\n *\n * Всё, что пакет не может знать сам: значения для дырок, куда класть каждый род ресурса и от\n * чего проект отказался. Конфиг лежит в дереве проекта и коммитится: раскладка обязана\n * повторяться на чужой машине без вопросов, иначе разложенное расходится между разработчиками.\n */\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/** Род ресурса. Он же имя каталога в `assets/` пакета и ключ раскладки. */\nexport type TKind =\n | 'laws'\n | 'rules'\n | 'patterns'\n | 'skills'\n | 'hooks'\n | 'defaults'\n | 'checks'\n | 'agents'\n | 'commands'\n | 'workflows'\n | 'templates'\n /** Документы дерева, которые читает и человек, и агент: словарь проекта. */\n | 'docs';\n\nexport const KINDS: readonly TKind[] = [\n 'laws',\n 'rules',\n 'patterns',\n 'skills',\n 'hooks',\n 'defaults',\n 'checks',\n 'agents',\n 'commands',\n 'workflows',\n 'templates',\n 'docs',\n];\n\n/**\n * Роды, которые ложатся не файлом в каталог, а каталогом по имени ресурса: скил читается как\n * `<имя>/SKILL.md`, и рядом с ним лежит то, что пишет проект.\n *\n * `skills` — скил, у которого нет закона над собой: он не про то, что должно быть верно в\n * продукте, а про то, как здесь делается работа. Правилом его называть нельзя — тогда придётся\n * выдумать ему закон, — а паттерном тем более: паттерн стоит при правиле.\n */\nexport const SKILL_KINDS: readonly TKind[] = ['rules', 'patterns', 'skills'];\n\n/** Имя файла скила: так его ищет агент, и другого имени у него быть не может. */\nexport const SKILL_FILE: string = 'SKILL.md';\n\n/**\n * Файл-компаньон правила: чем названо в этом дереве то, о чём правило говорит приёмом.\n *\n * Пакет знает приём, но не знает ни путей, ни имён — их пишет проект. Черновик кладётся один\n * раз и дальше не сверяется: это единственный файл раскладки, который принадлежит проекту.\n */\nexport const COMPANION_FILE: string = 'implementation.md';\n\nexport interface IConfig {\n /** Значения дырок `{{имя}}`. */\n readonly vars: Readonly<Record<string, string>>;\n /** Куда класть каждый род ресурса, путями от корня проекта. */\n readonly layout: Readonly<Record<TKind, string>>;\n /**\n * Ресурсы, которые проект выбрал, идентификаторами: `laws/access.md`. Пусто — берётся всё.\n * Ограничивает только те роды, которые сам называет; как именно — `isChosen`.\n */\n readonly only: readonly string[];\n /** Ресурсы, от которых проект отказался, идентификаторами: `laws/application/money.md`. */\n readonly skip: readonly string[];\n /**\n * Выбор проекта по осям различия: `{ \"host\": \"gitlab\" }`. Оси объявлены пакетом в\n * `assets/variants.json`, а ресурс с вариантом в имени берётся, только если проект выбрал\n * его значение; как именно — `isChosen`.\n */\n readonly variants: Readonly<Record<string, string>>;\n}\n\nexport const CONFIG_PATH: string = '.claude/rt-kit.json';\nexport const OVERRIDES_DIR: string = '.claude/rt-kit/overrides';\n\n/**\n * Карта «что правится — какое правило» и профиль дерева: команды, стенды, пары «правка —\n * документ». Оба лежат в двух видах, и это не дублирование, а разделение ответственности.\n *\n * Умолчание везёт пакет: проекты этой мастерской устроены одинаково — Nx, те же расширения, те\n * же имена каталогов, — и переписывать одну и ту же карту в каждом дереве заново значило бы\n * заводить пятнадцать её редакций, расходящихся молча. Оно разложено, под шапкой, и правится\n * не на месте.\n *\n * Надстройку пишет проект, и она необязательна: витрина, свой род файлов, другой запускатель\n * тестов есть не у всех. Объявленная в ней функция замещает умолчание целиком и вправе позвать\n * его обратно суффиксом `_default` — так дерево дописывает своё, не теряя общего.\n */\nexport const DEFAULTS_DIR: string = '.claude/rt-kit/defaults';\nexport const GATE_MAP_FILE: string = 'gate-map.sh';\nexport const PROFILE_FILE: string = 'project.sh';\n\n/**\n * Умолчания раскладки. Это не единственно возможные пути, но менять их без нужды не стоит:\n * агент ищет законы в `docs/constitution`, потому что так написано в правилах, которые пакет\n * же и везёт.\n */\nexport const DEFAULT_LAYOUT: Readonly<Record<TKind, string>> = {\n laws: 'docs/constitution',\n rules: '.claude/skills',\n patterns: '.claude/skills',\n skills: '.claude/skills',\n hooks: '.claude/hooks',\n defaults: DEFAULTS_DIR,\n checks: 'tools',\n agents: '.claude/agents',\n commands: '.claude/commands',\n workflows: '.claude/workflows',\n templates: '.claude/rt-kit/templates',\n docs: 'docs',\n};\n\nexport class ConfigError extends Error {}\n\nconst isRecord: (value: unknown) => value is Record<string, unknown> = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nfunction stringMap(value: unknown, where: string): Record<string, string> {\n if (value === undefined) {\n return {};\n }\n if (!isRecord(value)) {\n throw new ConfigError(`${where}: ожидается объект «имя — значение»`);\n }\n const result: Record<string, string> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (typeof entry !== 'string') {\n throw new ConfigError(`${where}.${key}: ожидается строка`);\n }\n result[key] = entry;\n }\n\n return result;\n}\n\nfunction idList(value: unknown, where: string): readonly string[] {\n const list: unknown = value ?? [];\n if (!Array.isArray(list) || list.some((entry: unknown): boolean => typeof entry !== 'string')) {\n throw new ConfigError(`${where}: ожидается список идентификаторов ресурсов`);\n }\n\n return list as string[];\n}\n\nexport function parseConfig(text: string): IConfig {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (error: unknown) {\n throw new ConfigError(`${CONFIG_PATH} — не разбирается как JSON: ${(error as Error).message}`);\n }\n if (!isRecord(raw)) {\n throw new ConfigError(`${CONFIG_PATH}: ожидается объект`);\n }\n\n const layout: Record<string, string> = { ...DEFAULT_LAYOUT, ...stringMap(raw['layout'], 'layout') };\n for (const kind of Object.keys(layout)) {\n if (!KINDS.includes(kind as TKind)) {\n throw new ConfigError(`layout.${kind}: такого рода ресурсов нет — есть ${KINDS.join(', ')}`);\n }\n }\n\n const only: readonly string[] = idList(raw['only'], 'only');\n const skip: readonly string[] = idList(raw['skip'], 'skip');\n\n // Пути раскладки — тоже значения проекта, и пакет их уже знает. Требовать их вторым списком\n // значило бы держать одно и то же в двух местах: расходятся такие пары молча.\n const derived: Record<string, string> = {};\n for (const kind of KINDS) {\n derived[`${kind.replace(/s$/, '')}sDir`] = layout[kind];\n }\n\n return {\n vars: { ...derived, ...stringMap(raw['vars'], 'vars') },\n layout: layout as Record<TKind, string>,\n only,\n skip,\n variants: stringMap(raw['variants'], 'variants'),\n };\n}\n\n/** Конфиг проекта; его отсутствие — не отказ, а повод сказать про `agent-kit init`. */\nexport function readConfig(root: string): IConfig | null {\n try {\n return parseConfig(readFileSync(join(root, CONFIG_PATH), 'utf8'));\n } catch (error: unknown) {\n if (error instanceof ConfigError) {\n throw error;\n }\n\n return null;\n }\n}\n"]}
@@ -1,15 +1,24 @@
1
1
  /** Настройка агента, в которой живёт карта. Путь от корня дерева. */
2
2
  export declare const SETTINGS_PATH: string;
3
3
  export interface IHookBinding {
4
- /** Событие агента: `PreToolUse`, `PostToolUse`, `SessionStart`. */
4
+ /** Событие агента: `PreToolUse`, `PostToolUse`, `SessionStart`, `Stop`. */
5
5
  readonly event: string;
6
- /** Образец, по которому событие достаётся этому гарду. */
6
+ /**
7
+ * Образец, по которому событие достаётся этому гарду. Пустой у события, которое не про
8
+ * инструмент: завершение хода приходит целиком, и выбирать в нём нечего.
9
+ */
7
10
  readonly matcher: string;
8
11
  /** Путь разложенного гарда от корня дерева. */
9
12
  readonly path: string;
10
13
  }
11
- /** Что гард говорит о себе. Молчит — он не подключается к агенту вовсе. */
12
- export declare function bindingOf(text: string, path: string): IHookBinding | null;
14
+ /**
15
+ * Что гард говорит о себе. Молчит он не подключается к агенту вовсе.
16
+ *
17
+ * Объявлений бывает несколько: гард, который сперва напоминает, а потом отбивает, стоит на двух
18
+ * событиях сразу. Разводить его по двум файлам значило бы держать два разбора одной записи и
19
+ * два места, где правится один порог.
20
+ */
21
+ export declare function bindingsOf(text: string, path: string): readonly IHookBinding[];
13
22
  /**
14
23
  * Раздел `hooks` для настройки агента: событие → образец → команда.
15
24
  *
@@ -19,6 +28,12 @@ export declare function bindingOf(text: string, path: string): IHookBinding | nu
19
28
  export declare function hooksSection(bindings: readonly IHookBinding[]): Record<string, unknown>;
20
29
  /** Пути гардов, названные в настройке агента этого дерева. Нет файла — ни одного. */
21
30
  export declare function boundInSettings(root: string): readonly string[];
22
- /** Разложенные гарды, которых в настройке агента нет: они лежат, но их никто не позовёт. */
31
+ /**
32
+ * Разложенные гарды, которых в настройке агента нет: они лежат, но их никто не позовёт.
33
+ *
34
+ * Разбор настройки называет пару «событие и путь», а падение назад — один путь. Поэтому
35
+ * подключённым считается и то, и другое: иначе дерево с настройкой, которую не разобрать,
36
+ * получало бы список из всех гардов разом.
37
+ */
23
38
  export declare function unboundHooks(bindings: readonly IHookBinding[], root: string): readonly IHookBinding[];
24
39
  //# sourceMappingURL=hooks-map.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks-map.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"AAmBA,qEAAqE;AACrE,eAAO,MAAM,aAAa,EAAE,MAAgC,CAAC;AAI7D,MAAM,WAAW,YAAY;IACzB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAIzE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkBvF;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAkB/D;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAIrG"}
1
+ {"version":3,"file":"hooks-map.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/hooks-map.ts"],"names":[],"mappings":"AAmBA,qEAAqE;AACrE,eAAO,MAAM,aAAa,EAAE,MAAgC,CAAC;AAI7D,MAAM,WAAW,YAAY;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAM9E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBvF;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAuC/D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAIrG"}