@rt-tools/agent-kit 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +15 -1
  2. package/assets/checks/check-push-gate.mjs +139 -0
  3. package/assets/checks/rt-kit-checks.config.mjs +11 -0
  4. package/assets/defaults/project.sh +1 -1
  5. package/assets/patterns/git-workflow-commit.azure.md +18 -0
  6. package/assets/patterns/git-workflow-commit.github.md +18 -0
  7. package/assets/patterns/git-workflow-commit.gitlab.md +18 -0
  8. package/assets/patterns/spec-driven-domain.md +2 -2
  9. package/assets/rules/git-workflow.azure.md +15 -0
  10. package/assets/rules/git-workflow.github.md +15 -0
  11. package/assets/rules/git-workflow.gitlab.md +15 -0
  12. package/lib/assets.d.ts +1 -1
  13. package/lib/assets.d.ts.map +1 -1
  14. package/lib/assets.js +2 -4
  15. package/lib/assets.js.map +1 -1
  16. package/lib/catalog.d.ts +73 -0
  17. package/lib/catalog.d.ts.map +1 -1
  18. package/lib/catalog.js +121 -0
  19. package/lib/catalog.js.map +1 -1
  20. package/lib/commands.d.ts.map +1 -1
  21. package/lib/commands.js +84 -5
  22. package/lib/commands.js.map +1 -1
  23. package/lib/integrity.d.ts +25 -12
  24. package/lib/integrity.d.ts.map +1 -1
  25. package/lib/integrity.js +40 -18
  26. package/lib/integrity.js.map +1 -1
  27. package/lib/proposals.d.ts +9 -1
  28. package/lib/proposals.d.ts.map +1 -1
  29. package/lib/proposals.js +11 -2
  30. package/lib/proposals.js.map +1 -1
  31. package/lib/retired.d.ts +30 -0
  32. package/lib/retired.d.ts.map +1 -0
  33. package/lib/retired.js +19 -0
  34. package/lib/retired.js.map +1 -0
  35. package/lib/sync.d.ts +45 -1
  36. package/lib/sync.d.ts.map +1 -1
  37. package/lib/sync.js +44 -10
  38. package/lib/sync.js.map +1 -1
  39. package/package.json +1 -1
  40. package/rt-tools-agent-kit-0.7.0.tgz +0 -0
  41. package/assets/laws/application/money.md +0 -41
  42. package/assets/laws/application/ownership.md +0 -32
  43. package/assets/patterns/ownership-scope-resolve.md +0 -69
  44. package/assets/patterns/ownership-session-procedure.md +0 -102
  45. package/assets/patterns/pricing-quote.md +0 -71
  46. package/assets/rules/ownership-scope.md +0 -66
  47. package/assets/rules/ownership-session.md +0 -124
  48. package/assets/rules/pricing.md +0 -68
  49. package/rt-tools-agent-kit-0.6.0.tgz +0 -0
package/README.md CHANGED
@@ -185,6 +185,19 @@ npx agent-kit init --laws access,delivery,verifiability
185
185
  трогает. Имена законов — из `agent-kit list`, там же видно, что взято, что не выбрано и что
186
186
  пропущено.
187
187
 
188
+ **Отказ от закона снимает его правила и паттерны сам.** Связь читается из вступления ресурсов —
189
+ у правила стоит `law`, у паттерна `rule`, — и перечислять потомков в `skip` не надо: строка,
190
+ которая после этого ничего не снимает, называется вслух предупреждением, а раскладка идёт
191
+ дальше. Каскад идёт только сверху вниз: отказ от паттерна ни правила, ни закона не трогает.
192
+
193
+ Правило, названное в `only` при невыбранном законе, тоже называется вслух: раскладка говорит,
194
+ что оно не приедет и по какому родителю. Файл такого правила, разложенный прежней настройкой,
195
+ перечисляется отдельно от брошенного — дерево от него не отказывалось.
196
+
197
+ Ресурс, ушедший из набора совсем, пакет помнит по имени: файл, положенный им в дерево прежней
198
+ редакцией, назван при раскладке вместе с причиной снятия. Убирает его дерево — в чужие файлы
199
+ пакет не пишет.
200
+
188
201
  ## Конфиг
189
202
 
190
203
  `.claude/rt-kit.json` коммитится: раскладка обязана повторяться на чужой машине без вопросов.
@@ -212,7 +225,8 @@ npx agent-kit init --laws access,delivery,verifiability
212
225
  называет: перечислив законы, проект говорит о законах, а не обо всём, что пакет везёт, —
213
226
  шаблоны при нём остаются.
214
227
  - **`skip`** — ресурсы, от которых проект отказался, теми же идентификаторами. Вычитает из
215
- выбранного, поэтому отказ от одного закона не требует переписывать весь список.
228
+ выбранного, поэтому отказ от одного закона не требует переписывать весь список. Правила при
229
+ отвергнутом законе и паттерны при них перечислять не надо: их снимает каскад.
216
230
 
217
231
  ## Надстройки
218
232
 
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Проверка того, что набор гейта пуша не уже набора конвейера.
4
+ *
5
+ * Гейт пуша — обещание, что пуш не приедет красным. Пока его набор уже набора
6
+ * конвейера, обещание шире того, что гейт проверяет, и неверно оно молча: ни
7
+ * гейт, ни его вывод не говорят, чего в нём нет. Дважды подряд правка, прошедшая
8
+ * гейт целиком, была отбита конвейером — и оба раза зелёный гейт был прочитан
9
+ * как «локально всё зелено».
10
+ *
11
+ * Файл конвейера машиной не толкуется: команды там произвольны, а часть шагов
12
+ * локально неисполнима вовсе — кэш, выгрузка следов, вход в реестр. Отсюда
13
+ * берутся только ИМЕНА шагов, а чем каждое из них закрывается в гейте,
14
+ * объявляет дерево. Необъявленное имя краснеет: дыра видна на месте, а не
15
+ * выводится сверкой двух списков глазами.
16
+ *
17
+ * Объявление бывает двух родов. Строка — та самая команда, которую печатает
18
+ * `rt_push_checks` профиля; она сверяется с его выводом, потому что объявление
19
+ * без исполнения — та же дыра. Исключение — причина, по которой шага в гейте
20
+ * нет; пустая причина исключением не считается: она единственное, чем
21
+ * постоянная дыра отличается от забытой строки.
22
+ *
23
+ * Дерево без файла конвейера сверки не получает: проверка, падающая там, где
24
+ * конвейера нет, отбивала бы работу вместо промаха.
25
+ *
26
+ * Ненулевой код возврата и перечень расхождений.
27
+ */
28
+ import { execFileSync } from 'node:child_process';
29
+ import { existsSync, readFileSync } from 'node:fs';
30
+ import { join } from 'node:path';
31
+
32
+ import { CONFIG, ROOT } from './rt-kit-checks.config.mjs';
33
+
34
+ const GATE = CONFIG.pushGate ?? {};
35
+ const PIPELINE = GATE.pipelineFile ?? '';
36
+ const DECLARED = GATE.steps ?? {};
37
+
38
+ /**
39
+ * Профиль дерева ищется той же цепочкой, что и у гарда пуша: умолчание пакета, поверх него
40
+ * надстройка проекта. Разойдись они — проверка судила бы не тот набор, который гоняет гард.
41
+ */
42
+ const PROFILES = ['.claude/rt-kit/defaults/project.sh', '.claude/rt-kit/project.sh'];
43
+
44
+ if (!PIPELINE || !existsSync(join(ROOT, PIPELINE))) {
45
+ console.log('check-push-gate: пропущено — файла конвейера в дереве нет');
46
+ process.exit(0);
47
+ }
48
+
49
+ /**
50
+ * Имена шагов конвейера. Образец задаёт дерево: у каждого хостинга своя форма записи, и
51
+ * угадывать её за все три пакет не берётся. Умолчание — форма GitHub Actions.
52
+ */
53
+ const stepPattern = new RegExp(GATE.stepPattern ?? '^\\s*-\\s*name:\\s*(.+?)\\s*$');
54
+
55
+ function pipelineSteps() {
56
+ return readFileSync(join(ROOT, PIPELINE), 'utf8')
57
+ .split('\n')
58
+ .map((line) => line.match(stepPattern)?.[1])
59
+ .filter(Boolean)
60
+ .map((name) => name.replace(/^['"]|['"]$/g, ''));
61
+ }
62
+
63
+ /**
64
+ * Набор гейта берётся у профиля его же оболочкой, а не переписывается сюда: два списка одного
65
+ * набора расходятся молча, и расходиться начинают в тот день, когда правят один из них.
66
+ *
67
+ * Профиля нет, функции в нём нет или оболочка отказала — набор неизвестен, и тогда проверка
68
+ * судит только полноту объявлений: сверять строки не с чем.
69
+ */
70
+ function gateChecks() {
71
+ const present = PROFILES.filter((path) => existsSync(join(ROOT, path)));
72
+ if (present.length === 0) {
73
+ return null;
74
+ }
75
+ const script = `${present.map((path) => `. "${path}"`).join('\n')}
76
+ command -v rt_push_checks >/dev/null 2>&1 || exit 42
77
+ rt_push_checks ""`;
78
+ try {
79
+ return execFileSync('bash', ['-c', script], { cwd: ROOT, encoding: 'utf8' })
80
+ .split('\n')
81
+ .map((line) => line.trim())
82
+ .filter(Boolean);
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ const steps = pipelineSteps();
89
+ const checks = gateChecks();
90
+ const problems = [];
91
+
92
+ for (const step of steps) {
93
+ const declaration = DECLARED[step];
94
+
95
+ if (declaration === undefined) {
96
+ problems.push(
97
+ `шаг конвейера «${step}» не объявлен: закрой его строкой набора в pushGate.steps ` + 'либо объяви исключением с причиной'
98
+ );
99
+ continue;
100
+ }
101
+
102
+ if (typeof declaration === 'object' && declaration !== null) {
103
+ const reason = String(declaration.skip ?? '').trim();
104
+ if (!reason) {
105
+ problems.push(`шаг конвейера «${step}» объявлен исключением без причины — пустая причина не считается`);
106
+ }
107
+ continue;
108
+ }
109
+
110
+ const line = String(declaration).trim();
111
+ if (!line) {
112
+ problems.push(`шаг конвейера «${step}» объявлен пустой строкой — назови команду либо объяви исключение`);
113
+ continue;
114
+ }
115
+
116
+ if (checks && !checks.some((check) => check.includes(line))) {
117
+ problems.push(`шаг конвейера «${step}» объявлен строкой «${line}», а набор гейта её не печатает`);
118
+ }
119
+ }
120
+
121
+ /** Строка о шаге, которого в конвейере нет, — устаревшая: иначе объявления копят мёртвое. */
122
+ const known = new Set(steps);
123
+ for (const step of Object.keys(DECLARED)) {
124
+ if (!known.has(step)) {
125
+ problems.push(`объявление «${step}» устарело — такого шага в ${PIPELINE} нет`);
126
+ }
127
+ }
128
+
129
+ if (problems.length > 0) {
130
+ console.error(`check-push-gate: расхождений ${problems.length}\n`);
131
+ problems.forEach((problem) => console.error(` ${problem}`));
132
+ console.error('\nНабор гейта пуша не бывает уже набора конвейера — правило поставки.');
133
+ process.exit(1);
134
+ }
135
+
136
+ const skipped = Object.values(DECLARED).filter((value) => typeof value === 'object' && value !== null).length;
137
+ console.log(
138
+ `check-push-gate: шагов конвейера ${steps.length}, закрыто набором ${steps.length - skipped}, ` + `объявлено исключениями ${skipped}`
139
+ );
@@ -84,6 +84,17 @@ const DEFAULTS = {
84
84
  * не считается никогда.
85
85
  */
86
86
  productionMarks: [],
87
+ /**
88
+ * Гейт пуша против конвейера. `pipelineFile` — файл, из которого берутся имена шагов;
89
+ * пусто или файла нет — сверки нет вовсе. `stepPattern` — чем имя шага оттуда достаётся;
90
+ * умолчание записано под GitHub Actions. `steps` — чем каждое имя закрыто: строка набора
91
+ * либо `{ "skip": "<причина>" }`. Необъявленный шаг отбивает пуш.
92
+ */
93
+ pushGate: {
94
+ pipelineFile: '',
95
+ stepPattern: '^\\s*-\\s*name:\\s*(.+?)\\s*$',
96
+ steps: {},
97
+ },
87
98
  /** Очередь работ: владелец, репозиторий, борда и учётная запись машинной работы. */
88
99
  board: {
89
100
  owner: '',
@@ -58,7 +58,7 @@ rt_push_checks_default() {
58
58
  [ -x "$root/$RT_HOOKS_TESTS" ] && printf '%s\n' "bash $RT_HOOKS_TESTS"
59
59
 
60
60
  for check in check-doc-paths check-specs check-file-size check-dupes check-styles \
61
- check-lib-layers check-reuse check-schema-drift; do
61
+ check-lib-layers check-reuse check-schema-drift check-push-gate; do
62
62
  [ -f "$root/$RT_CHECKS_DIR/$check.mjs" ] && printf '%s\n' "node $RT_CHECKS_DIR/$check.mjs"
63
63
  done
64
64
 
@@ -201,6 +201,11 @@ az repos pr show --id 205 \
201
201
 
202
202
  Владельцу называют то, что прочитали, а не то, что заказывали.
203
203
 
204
+ Перечитывают его и по времени, а не только после вызовов, которые молча ничего не сделали:
205
+ состояние PR читается перед тем, как что-либо о нём сказать. Между «прогон зелёный» и следующей
206
+ фразой владелец успевает влить PR, и всё сказанное о нём после этого — про вчерашний день. Так
207
+ владельцу и было предложено влить то, что он влил часом раньше.
208
+
204
209
  Открытый PR означает, что элемент ждёт разбора, — состояние переставляется тем же движением:
205
210
 
206
211
  ```bash
@@ -236,6 +241,14 @@ npm run task:move -- 86 in-review
236
241
  сделано>`, тем же номером, что стоит у элемента и в имени ветки.
237
242
  12. **Очередь работ сходится** — `npm run check:board`.
238
243
  13. **Состояние PR прочитано, а не выведено из кодов возврата.**
244
+ 14. **Набор взят из файла конвейера, а не собран по памяти.** Гейт пуша заведомо уже: он стоит
245
+ между командой и пушем, и всё, что дольше секунд, из него вынесено. Что гоняет конвейер,
246
+ написано в его файле — этот список и повторяется локально; зелёный гейт полнотой набора не
247
+ является.
248
+ 15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
249
+ теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
250
+ снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
251
+ отчёт.
239
252
 
240
253
  Сразу после публикации элемент переводится в разбор, и сверка очереди прогоняется ещё раз: до
241
254
  открытия PR состояние она не судит, а после открытия расхождение видит.
@@ -243,6 +256,11 @@ npm run task:move -- 86 in-review
243
256
  Сделанное рассуждением и сделанное замером в теле PR разводятся прямо: непроверенное,
244
257
  названное проверенным, ревьювер принимает за проверенное.
245
258
 
259
+ **Раздел «Чем подтверждено» называет и то, что не гонялось.** Список одного прогнанного
260
+ неотличим от полного набора, и ревьювер по нему решает, что можно не перепроверять. Цена ошибки
261
+ здесь не красный конвейер, а доверие к разделу: однажды прочитанный как полнота, дальше он
262
+ перепроверяется весь.
263
+
246
264
  ## Частые промахи
247
265
 
248
266
  - Область и итерация не заданы: элемент заведён, но на доску команды не попал.
@@ -249,6 +249,11 @@ $GH api "repos/$REPO/pulls/321" \
249
249
  Учётная запись, из-под которой пришлось пушить, в этот вызов не переносится: пуш и авторство
250
250
  PR выбираются отдельно, и `GH_TOKEN` для публикации — всегда токен бота.
251
251
 
252
+ Перечитывают его и по времени, а не только после вызовов, которые молча ничего не сделали:
253
+ состояние PR читается перед тем, как что-либо о нём сказать. Между «прогон зелёный» и следующей
254
+ фразой владелец успевает влить PR, и всё сказанное о нём после этого — про вчерашний день. Так
255
+ владельцу и было предложено влить то, что он влил часом раньше.
256
+
252
257
  Открытый PR означает, что задача ждёт разбора, — колонка переставляется тем же движением:
253
258
 
254
259
  ```bash
@@ -293,6 +298,14 @@ npm run task:move -- 86 in-review
293
298
  номером в заголовке; PR один на задачу, и закрывает он её целиком.
294
299
  13. **Состояние PR прочитано, а не выведено из кодов возврата** — автор `<бот>`,
295
300
  ревьювер — владелец, метки те же, что у задачи. Владельцу называют прочитанное.
301
+ 14. **Набор взят из файла конвейера, а не собран по памяти.** Гейт пуша заведомо уже: он стоит
302
+ между командой и пушем, и всё, что дольше секунд, из него вынесено. Что гоняет конвейер,
303
+ написано в его файле — этот список и повторяется локально; зелёный гейт полнотой набора не
304
+ является.
305
+ 15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
306
+ теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
307
+ снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
308
+ отчёт.
296
309
 
297
310
  Сразу после публикации задача переставляется в разбор — `npm run task:move -- <номер>
298
311
  in-review`, — и `npm run check:board` прогоняется ещё раз: до открытия PR колонку он не судит,
@@ -301,6 +314,11 @@ in-review`, — и `npm run check:board` прогоняется ещё раз:
301
314
  Сделанное рассуждением и сделанное замером в теле PR разводятся прямо: непроверенное,
302
315
  названное проверенным, ревьювер принимает за проверенное.
303
316
 
317
+ **Раздел «Чем подтверждено» называет и то, что не гонялось.** Список одного прогнанного
318
+ неотличим от полного набора, и ревьювер по нему решает, что можно не перепроверять. Цена ошибки
319
+ здесь не красный конвейер, а доверие к разделу: однажды прочитанный как полнота, дальше он
320
+ перепроверяется весь.
321
+
304
322
  ## Частые промахи
305
323
 
306
324
  - `gh` в оболочке пользователя подменён — звать `/opt/homebrew/bin/gh` напрямую.
@@ -221,6 +221,11 @@ glab mr view 205 --output json \
221
221
  Учётная запись, из-под которой пришлось пушить, в этот вызов не переносится: пуш и авторство
222
222
  MR выбираются отдельно, и токен для публикации — всегда токен машинной работы.
223
223
 
224
+ Перечитывают его и по времени, а не только после вызовов, которые молча ничего не сделали:
225
+ состояние MR читается перед тем, как что-либо о нём сказать. Между «прогон зелёный» и следующей
226
+ фразой владелец успевает влить MR, и всё сказанное о нём после этого — про вчерашний день. Так
227
+ владельцу и было предложено влить то, что он влил часом раньше.
228
+
224
229
  Открытый MR означает, что задача ждёт разбора, — список переставляется тем же движением:
225
230
 
226
231
  ```bash
@@ -256,6 +261,14 @@ npm run task:move -- 86 in-review
256
261
  сделано>`, тем же номером, что стоит у задачи и в имени ветки.
257
262
  12. **Очередь работ сходится** — `npm run check:board`.
258
263
  13. **Состояние MR прочитано, а не выведено из кодов возврата.**
264
+ 14. **Набор взят из файла конвейера, а не собран по памяти.** Гейт пуша заведомо уже: он стоит
265
+ между командой и пушем, и всё, что дольше секунд, из него вынесено. Что гоняет конвейер,
266
+ написано в его файле — этот список и повторяется локально; зелёный гейт полнотой набора не
267
+ является.
268
+ 15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
269
+ теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
270
+ снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
271
+ отчёт.
259
272
 
260
273
  Сразу после публикации задача переставляется в разбор, и сверка очереди прогоняется ещё раз: до
261
274
  открытия MR список она не судит, а после открытия расхождение видит.
@@ -263,6 +276,11 @@ npm run task:move -- 86 in-review
263
276
  Сделанное рассуждением и сделанное замером в теле MR разводятся прямо: непроверенное,
264
277
  названное проверенным, ревьювер принимает за проверенное.
265
278
 
279
+ **Раздел «Чем подтверждено» называет и то, что не гонялось.** Список одного прогнанного
280
+ неотличим от полного набора, и ревьювер по нему решает, что можно не перепроверять. Цена ошибки
281
+ здесь не красный конвейер, а доверие к разделу: однажды прочитанный как полнота, дальше он
282
+ перепроверяется весь.
283
+
266
284
  ## Частые промахи
267
285
 
268
286
  - Метка списка не поставлена при заведении: задача есть, а на доске её нет. Доска показывает
@@ -48,8 +48,8 @@ docs/specs/<домен>/
48
48
  процедуры домен обслуживает.
49
49
 
50
50
  ```markdown
51
- **Зависимости:** `pricing` (сумма заявки), `availability` (занятость дат)
52
- **Законы:** `access`, `locales`, `money`, `ownership`
51
+ **Зависимости:** `catalog` (состав заявки), `availability` (занятость дат)
52
+ **Законы:** `access`, `locales`, `lists`
53
53
  **Процедуры:** `libs/api/<домен>`
54
54
  ```
55
55
 
@@ -108,6 +108,21 @@ description: Правило под «Закон о поставке» для д
108
108
  только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
109
109
  образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
110
110
  выкатку.
111
+ - **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
112
+ красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
113
+ конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
114
+ отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
115
+ разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером — и оба раза
116
+ зелёный гейт был прочитан как «локально всё зелено».
117
+ - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
118
+ теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
119
+ проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
120
+ снимки витрин с того момента, как вливание принесло чужую правку оформления.
121
+ - **Утверждение о главной ветке делается по удалённой ссылке, а не по локальной.** Локальная
122
+ протухает в ту минуту, когда её подтянули в последний раз, и молчит об этом: она не пуста и не
123
+ сломана, она описывает вчерашний день. Сравнение веток пишется от `origin/main` целиком —
124
+ смешав в одной команде удалённую ссылку для одной стороны и локальную для другой, промах
125
+ изнутри выглядит правильным.
111
126
  - **Рабочий элемент привязывается к PR при создании, а не после.** `az repos pr create`
112
127
  принимает `--work-items`; привязка второй командой обходится молча, когда у токена нет права
113
128
  править чужой элемент, и PR остаётся ни с чем не связанным.
@@ -118,6 +118,21 @@ description: Правило под «Закон о поставке» для д
118
118
  - **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
119
119
  только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
120
120
  образа, то есть до мержа. Четыре мержа подряд так и уехали в главную ветку, ломая выкатку.
121
+ - **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
122
+ красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
123
+ конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
124
+ отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
125
+ разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером — и оба раза
126
+ зелёный гейт был прочитан как «локально всё зелено».
127
+ - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
128
+ теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
129
+ проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
130
+ снимки витрин с того момента, как вливание принесло чужую правку оформления.
131
+ - **Утверждение о главной ветке делается по удалённой ссылке, а не по локальной.** Локальная
132
+ протухает в ту минуту, когда её подтянули в последний раз, и молчит об этом: она не пуста и не
133
+ сломана, она описывает вчерашний день. Сравнение веток пишется от `origin/main` целиком —
134
+ смешав в одной команде удалённую ссылку для одной стороны и локальную для другой, промах
135
+ изнутри выглядит правильным.
121
136
  - **Автор PR не может быть его ревьювером.** Запрос разбора на самого себя GitHub принимает и
122
137
  молча не создаёт — разбор при этом выглядит запрошенным.
123
138
  - **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit`.** На
@@ -108,6 +108,21 @@ description: Правило под «Закон о поставке» для д
108
108
  только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
109
109
  образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
110
110
  выкатку.
111
+ - **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
112
+ красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
113
+ конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
114
+ отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
115
+ разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером — и оба раза
116
+ зелёный гейт был прочитан как «локально всё зелено».
117
+ - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
118
+ теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
119
+ проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
120
+ снимки витрин с того момента, как вливание принесло чужую правку оформления.
121
+ - **Утверждение о главной ветке делается по удалённой ссылке, а не по локальной.** Локальная
122
+ протухает в ту минуту, когда её подтянули в последний раз, и молчит об этом: она не пуста и не
123
+ сломана, она описывает вчерашний день. Сравнение веток пишется от `origin/main` целиком —
124
+ смешав в одной команде удалённую ссылку для одной стороны и локальную для другой, промах
125
+ изнутри выглядит правильным.
111
126
  - **Слияние по кнопке «Merge when pipeline succeeds» не заменяет проверок до пуша.** Конвейер
112
127
  видит только то, что уже отправлено, а отправленная красная ветка занимает очередь работ и
113
128
  выглядит готовой к разбору.
package/lib/assets.d.ts CHANGED
@@ -19,6 +19,6 @@ export interface IAsset {
19
19
  * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом
20
20
  * дереве нет, а агенту, который правило читает, различать их незачем.
21
21
  */
22
- export declare function targetOf(entry: IEntryOfCatalog, layout: Readonly<Record<TKind, string>>): string;
22
+ export declare function targetOf(entry: Pick<IEntryOfCatalog, 'id' | 'kind' | 'name'>, layout: Readonly<Record<TKind, string>>): string;
23
23
  export declare function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[];
24
24
  //# sourceMappingURL=assets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAyB,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,OAAO,EAA2B,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,MAAM;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAUD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAIhG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAWnF"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,eAAe,EAAe,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,OAAO,EAA2B,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,MAAM;IACnB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAUD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAI9H;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CASnF"}
package/lib/assets.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.
7
7
  */
8
8
  import { join } from 'node:path';
9
- import { isChosen, readCatalog } from './catalog.js';
9
+ import { chosenEntries, readCatalog } from './catalog.js';
10
10
  import { SKILL_FILE, SKILL_KINDS } from './config.js';
11
11
  /** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */
12
12
  const extensionOf = (id) => {
@@ -27,9 +27,7 @@ export function targetOf(entry, layout) {
27
27
  : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);
28
28
  }
29
29
  export function collectAssets(config, assetsDir) {
30
- return readCatalog(assetsDir)
31
- .filter((entry) => isChosen(entry, config))
32
- .map((entry) => ({
30
+ return chosenEntries(readCatalog(assetsDir), config).map((entry) => ({
33
31
  id: entry.id,
34
32
  kind: entry.kind,
35
33
  name: entry.name,
package/lib/assets.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAmB,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAW,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAetE,kFAAkF;AAClF,MAAM,WAAW,GAA2B,CAAC,EAAU,EAAU,EAAE;IAC/D,MAAM,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAsB,EAAE,MAAuC;IACpF,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,SAAiB;IAC5D,OAAO,WAAW,CAAC,SAAS,CAAC;SACxB,MAAM,CAAC,CAAC,KAAsB,EAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;SACpE,GAAG,CAAC,CAAC,KAAsB,EAAU,EAAE,CAAC,CAAC;QACtC,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC/B,CAAC,CAAC,CAAC;AACZ,CAAC","sourcesContent":["/**\n * Что из везомого пакетом взял этот проект и куда оно ложится.\n *\n * Полный набор читает `catalog.ts`, здесь из него остаётся выбранное. Разделено потому, что\n * выбирать приходится раньше, чем раскладывать: `init` спрашивает, какие законы взять, а `list`\n * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.\n */\nimport { join } from 'node:path';\n\nimport { IEntryOfCatalog, isChosen, readCatalog } from './catalog.js';\nimport { IConfig, SKILL_FILE, SKILL_KINDS, TKind } from './config.js';\n\nexport interface IAsset {\n /** Идентификатор: `laws/application/money.md`. Он же путь надстройки и ключ в `only` и `skip`. */\n readonly id: string;\n readonly kind: TKind;\n /** Имя без рода, вида и расширения: `delivery`. У скила — имя каталога, которым его зовут. */\n readonly name: string;\n readonly text: string;\n /** Путь в дереве проекта, куда ресурс ложится. */\n readonly target: string;\n /** Запускается ли файл сам по себе: гарда без права на запуск не существует. */\n readonly executable: boolean;\n}\n\n/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */\nconst extensionOf: (id: string) => string = (id: string): string => {\n const dot: number = id.lastIndexOf('.');\n const slash: number = id.lastIndexOf('/');\n\n return dot > slash ? id.slice(dot) : '';\n};\n\n/**\n * Куда ложится ресурс. Скил читается агентом как `<имя>/SKILL.md`, и другого имени у него быть\n * не может: файл, названный по ресурсу, агент не найдёт вовсе. Остальные роды ложатся файлом —\n * по имени, а не по идентификатору: слой законов из идентификатора в путь переезжает, а вид\n * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом\n * дереве нет, а агенту, который правило читает, различать их незачем.\n */\nexport function targetOf(entry: IEntryOfCatalog, layout: Readonly<Record<TKind, string>>): string {\n return SKILL_KINDS.includes(entry.kind)\n ? join(layout[entry.kind], entry.name, SKILL_FILE)\n : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);\n}\n\nexport function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[] {\n return readCatalog(assetsDir)\n .filter((entry: IEntryOfCatalog): boolean => isChosen(entry, config))\n .map((entry: IEntryOfCatalog): IAsset => ({\n id: entry.id,\n kind: entry.kind,\n name: entry.name,\n text: entry.text,\n target: targetOf(entry, config.layout),\n executable: entry.executable,\n }));\n}\n"]}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAW,UAAU,EAAE,WAAW,EAAS,MAAM,aAAa,CAAC;AAetE,kFAAkF;AAClF,MAAM,WAAW,GAA2B,CAAC,EAAU,EAAU,EAAE;IAC/D,MAAM,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoD,EAAE,MAAuC;IAClH,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAe,EAAE,SAAiB;IAC5D,OAAO,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAU,EAAE,CAAC,CAAC;QAC1F,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC/B,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["/**\n * Что из везомого пакетом взял этот проект и куда оно ложится.\n *\n * Полный набор читает `catalog.ts`, здесь из него остаётся выбранное. Разделено потому, что\n * выбирать приходится раньше, чем раскладывать: `init` спрашивает, какие законы взять, а `list`\n * показывает и то, от чего проект отказался, — обоим нужен набор до отбора.\n */\nimport { join } from 'node:path';\n\nimport { chosenEntries, IEntryOfCatalog, readCatalog } from './catalog.js';\nimport { IConfig, SKILL_FILE, SKILL_KINDS, TKind } from './config.js';\n\nexport interface IAsset {\n /** Идентификатор: `laws/application/money.md`. Он же путь надстройки и ключ в `only` и `skip`. */\n readonly id: string;\n readonly kind: TKind;\n /** Имя без рода, вида и расширения: `delivery`. У скила — имя каталога, которым его зовут. */\n readonly name: string;\n readonly text: string;\n /** Путь в дереве проекта, куда ресурс ложится. */\n readonly target: string;\n /** Запускается ли файл сам по себе: гарда без права на запуск не существует. */\n readonly executable: boolean;\n}\n\n/** Расширение ресурса вместе с точкой; у файла без расширения — пустая строка. */\nconst extensionOf: (id: string) => string = (id: string): string => {\n const dot: number = id.lastIndexOf('.');\n const slash: number = id.lastIndexOf('/');\n\n return dot > slash ? id.slice(dot) : '';\n};\n\n/**\n * Куда ложится ресурс. Скил читается агентом как `<имя>/SKILL.md`, и другого имени у него быть\n * не может: файл, названный по ресурсу, агент не найдёт вовсе. Остальные роды ложатся файлом —\n * по имени, а не по идентификатору: слой законов из идентификатора в путь переезжает, а вид\n * ресурса нет. У разложенного `git-workflow` хостинга в имени не остаётся: второго вида в этом\n * дереве нет, а агенту, который правило читает, различать их незачем.\n */\nexport function targetOf(entry: Pick<IEntryOfCatalog, 'id' | 'kind' | 'name'>, layout: Readonly<Record<TKind, string>>): string {\n return SKILL_KINDS.includes(entry.kind)\n ? join(layout[entry.kind], entry.name, SKILL_FILE)\n : join(layout[entry.kind], `${entry.name}${extensionOf(entry.id)}`);\n}\n\nexport function collectAssets(config: IConfig, assetsDir: string): readonly IAsset[] {\n return chosenEntries(readCatalog(assetsDir), config).map((entry: IEntryOfCatalog): IAsset => ({\n id: entry.id,\n kind: entry.kind,\n name: entry.name,\n text: entry.text,\n target: targetOf(entry, config.layout),\n executable: entry.executable,\n }));\n}\n"]}
package/lib/catalog.d.ts CHANGED
@@ -30,6 +30,22 @@ export interface IEntryOfCatalog {
30
30
  */
31
31
  readonly requires: readonly string[];
32
32
  }
33
+ /** Что объявила шапка ресурса. Пустое поле и отсутствующее здесь одно и то же. */
34
+ export interface IFrontMatter {
35
+ readonly name: string;
36
+ readonly kind: string;
37
+ /** Закон, под которым стоит правило. */
38
+ readonly law: string;
39
+ /** Правило, при котором стоит паттерн. */
40
+ readonly rule: string;
41
+ }
42
+ /**
43
+ * Вступление между `---` в начале файла; его нет — вернётся пустая шапка.
44
+ *
45
+ * Живёт при каталоге, потому что связь родителя с потомком читают двое: сверка связности пакета
46
+ * и каскад отказа. Объявление у одного из них заводило бы круговой импорт между ними.
47
+ */
48
+ export declare function frontMatterOf(text: string): IFrontMatter;
33
49
  /**
34
50
  * Что ресурс о себе объявил. Имена читаются идентификаторами — `hooks/observe.sh`: короткая
35
51
  * форма совпала бы у закона и правила с одним именем, а требование, указавшее не туда, хуже
@@ -91,6 +107,63 @@ export interface IGapOfVariant {
91
107
  * существующие в `skip` — дерево тем самым говорит, что обходится без этого ресурса.
92
108
  */
93
109
  export declare function variantGaps(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IGapOfVariant[];
110
+ /** Ресурс, снятый вслед за отвергнутым родителем. */
111
+ export interface ICascadeCut {
112
+ readonly id: string;
113
+ /** Ближайший родитель: у правила — его закон, у паттерна — его правило. */
114
+ readonly parent: string;
115
+ /**
116
+ * Отвергнутый корень цепочки — то, что дерево действительно отвергло или не выбрало.
117
+ * Ближайшего родителя мало: паттерн уходит вслед за правилом, которого в отказе нет, и
118
+ * искать его там читатель пойдёт зря.
119
+ */
120
+ readonly root: string;
121
+ }
122
+ /**
123
+ * Ресурсы, снятые каскадом: правила при невзятом законе и паттерны при невзятых правилах.
124
+ *
125
+ * Связь читается из вступления самого ресурса — отдельный список при пакете разошёлся бы с
126
+ * ресурсами молча, тем же молчанием, ради которого каскад и заводится. Родитель ищется по
127
+ * последнему звену имени: полного пути в шапке нет, потому что переезд закона между слоями
128
+ * переписывал бы шапки всех правил при нём.
129
+ *
130
+ * Родителя в каталоге нет вовсе — каскад молчит: снимать не по чему, а промах в шапке судит
131
+ * сверка связности пакета, до всякой раскладки в дереве.
132
+ */
133
+ export declare function cascadeCuts(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[];
134
+ /**
135
+ * Ресурсы, названные выбором поимённо и всё равно снятые каскадом.
136
+ *
137
+ * Дерево, назвавшее правило в выборе при невыбранном законе, не получает его молча — то самое
138
+ * молчание, ради которого каскад и заводится, только с другой стороны: там о снятии не знал тот,
139
+ * кто ничего не просил, здесь — тот, кто попросил прямо.
140
+ */
141
+ export declare function namedButCut(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly ICascadeCut[];
142
+ /**
143
+ * Что ложится в дерево: прямой отбор за вычетом снятого каскадом.
144
+ *
145
+ * Отдельной функцией, а не внутри `isChosen`, потому что каскад знает весь каталог, а отбор —
146
+ * один ресурс: связь родителя с потомком по одной записи не видна.
147
+ */
148
+ export declare function chosenEntries(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IEntryOfCatalog[];
149
+ /** Строка отказа, которая ничего не снимает. */
150
+ export interface IIdleSkip {
151
+ readonly id: string;
152
+ /** Чем названное ею уже снято: имя отвергнутого родителя, либо пусто — такого ресурса нет. */
153
+ readonly by: string;
154
+ }
155
+ /**
156
+ * Строки отказа, которые ничего не снимают: названное ими снято каскадом или в каталоге не
157
+ * значится вовсе.
158
+ *
159
+ * Не отказ, а предупреждение: настройка, верная до обновления пакета, становится лишней сама,
160
+ * без единой правки в дереве, и отбивать за это раскладку значило бы наказывать за вчерашнюю
161
+ * правоту.
162
+ *
163
+ * Строка на ресурс чужого вида лишней не считается никогда: ею дерево гасит отказ о ресурсе,
164
+ * у которого нет подходящего вида, — то есть работу она делает.
165
+ */
166
+ export declare function idleSkips(catalog: readonly IEntryOfCatalog[], selection: ISelection): readonly IIdleSkip[];
94
167
  /** Выбранный ресурс, чьё требование в дерево не поехало. */
95
168
  export interface IBrokenLink {
96
169
  /** Кто требует — идентификатор выбранного ресурса. */
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/catalog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/catalog.ts"],"names":[],"mappings":"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"}