@rt-tools/agent-kit 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/assets/checks/check-push-gate.mjs +139 -0
- package/assets/checks/check-reuse.mjs +32 -98
- package/assets/checks/rt-kit-checks.config.mjs +19 -0
- package/assets/checks/signals/angular.json +19 -0
- package/assets/checks/signals/core.json +19 -0
- package/assets/checks/signals/store.json +14 -0
- package/assets/checks/signals/ui-kit-v2.json +48 -0
- package/assets/checks/signals/ui-kit.json +11 -0
- package/assets/checks/signals/utils.json +15 -0
- package/assets/checks/signals.mjs +71 -0
- package/assets/defaults/project.sh +9 -7
- package/assets/hooks/reuse-first-guard.sh +90 -1
- package/assets/patterns/git-workflow-commit.azure.md +18 -0
- package/assets/patterns/git-workflow-commit.github.md +18 -0
- package/assets/patterns/git-workflow-commit.gitlab.md +18 -0
- package/assets/patterns/reuse-first-extend.md +30 -0
- package/assets/patterns/spec-driven-domain.md +2 -2
- package/assets/rules/git-workflow.azure.md +15 -0
- package/assets/rules/git-workflow.github.md +15 -0
- package/assets/rules/git-workflow.gitlab.md +15 -0
- package/assets/rules/reuse-first.md +31 -13
- package/assets/skills/agent-kit.md +13 -8
- package/lib/assets.d.ts +1 -1
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +2 -4
- package/lib/assets.js.map +1 -1
- package/lib/catalog.d.ts +73 -0
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +121 -0
- package/lib/catalog.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +84 -5
- package/lib/commands.js.map +1 -1
- package/lib/integrity.d.ts +25 -12
- package/lib/integrity.d.ts.map +1 -1
- package/lib/integrity.js +40 -18
- package/lib/integrity.js.map +1 -1
- package/lib/proposals.d.ts +9 -1
- package/lib/proposals.d.ts.map +1 -1
- package/lib/proposals.js +11 -2
- package/lib/proposals.js.map +1 -1
- package/lib/retired.d.ts +30 -0
- package/lib/retired.d.ts.map +1 -0
- package/lib/retired.js +19 -0
- package/lib/retired.js.map +1 -0
- package/lib/sync.d.ts +45 -1
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +44 -10
- package/lib/sync.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.8.0.tgz +0 -0
- package/assets/laws/application/money.md +0 -41
- package/assets/laws/application/ownership.md +0 -32
- package/assets/patterns/ownership-scope-resolve.md +0 -69
- package/assets/patterns/ownership-session-procedure.md +0 -102
- package/assets/patterns/pricing-quote.md +0 -71
- package/assets/rules/ownership-scope.md +0 -66
- package/assets/rules/ownership-session.md +0 -124
- package/assets/rules/pricing.md +0 -68
- package/rt-tools-agent-kit-0.6.0.tgz +0 -0
|
@@ -132,8 +132,90 @@ has_re() {
|
|
|
132
132
|
printf '%s' "$1" | RT_RE="$2" perl -0777 -ne 'exit(/$ENV{RT_RE}/s ? 0 : 1)' 2>/dev/null
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
# Что дерево объявило своим: наборы признаков и файл собственных. Настройка проверок — та же,
|
|
136
|
+
# что читает сплошная проверка; каталог наборов называет профиль дерева, потому что раскладка
|
|
137
|
+
# проверок у каждого дерева своя.
|
|
138
|
+
rt_checks_json="${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/checks.json"
|
|
139
|
+
rt_bundles=''
|
|
140
|
+
rt_own_signals=''
|
|
141
|
+
if [ -f "$rt_checks_json" ]; then
|
|
142
|
+
rt_bundles="$(jq -r '.reuse.bundles[]? // empty' "$rt_checks_json" 2>/dev/null | tr '\n' ' ')"
|
|
143
|
+
own="$(jq -r '.reuse.signals // empty' "$rt_checks_json" 2>/dev/null)"
|
|
144
|
+
[ -n "$own" ] && rt_own_signals="${CLAUDE_PROJECT_DIR:-.}/$own"
|
|
145
|
+
fi
|
|
146
|
+
rt_signals_dir="${CLAUDE_PROJECT_DIR:-.}/${RT_REUSE_SIGNALS_DIR:-tools/signals}"
|
|
147
|
+
|
|
148
|
+
# Признаки объявленных наборов: те же файлы читает сплошная проверка. Ключ признака совпал с
|
|
149
|
+
# ключом дерева — побеждает дерево: оно видит своё готовое, а пакет его не видел.
|
|
150
|
+
signals_json() {
|
|
151
|
+
[ -n "$rt_signals_dir" ] || return 0
|
|
152
|
+
[ -d "$rt_signals_dir" ] || return 0
|
|
153
|
+
# Шапка раскладки снимается до разбора: в JSON комментария нет, и с ней разбор падает.
|
|
154
|
+
for name in $rt_bundles; do
|
|
155
|
+
file="$rt_signals_dir/$name.json"
|
|
156
|
+
[ -f "$file" ] && grep -v '^# rt-kit ' "$file" | jq -c '.signals[]?' 2>/dev/null
|
|
157
|
+
done
|
|
158
|
+
[ -n "$rt_own_signals" ] && [ -f "$rt_own_signals" ] && grep -v '^# rt-kit ' "$rt_own_signals" | jq -c '.signals[]?' 2>/dev/null
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# Поля читаются по одному, а не разбором строки: таб в `IFS` — пробельный разделитель, и пустое
|
|
162
|
+
# поле в середине схлопывается, из-за чего совет уезжает в образец отмены и гасит признак молча.
|
|
163
|
+
field() { printf '%s' "$1" | jq -r "$2 // empty" 2>/dev/null; }
|
|
164
|
+
|
|
135
165
|
found=''
|
|
136
|
-
|
|
166
|
+
signals_seen=0
|
|
167
|
+
while IFS= read -r signal; do
|
|
168
|
+
[ -z "$signal" ] && continue
|
|
169
|
+
signals_seen=1
|
|
170
|
+
ext="$(field "$signal" '.ext')"
|
|
171
|
+
case "$ext" in
|
|
172
|
+
'') ;;
|
|
173
|
+
*) case "$path" in *"$ext") ;; *) continue ;; esac ;;
|
|
174
|
+
esac
|
|
175
|
+
only_named="$(field "$signal" '.onlyNamed')"
|
|
176
|
+
if [ -n "$only_named" ]; then
|
|
177
|
+
printf '%s' "${path##*/}" | grep -qE "$only_named" || continue
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
case "$(field "$signal" '.scope')" in
|
|
181
|
+
whole) text="$whole" ;;
|
|
182
|
+
*) text="$added" ;;
|
|
183
|
+
esac
|
|
184
|
+
|
|
185
|
+
pattern="$(field "$signal" '.find')"
|
|
186
|
+
[ -z "$pattern" ] && continue
|
|
187
|
+
strip="$(field "$signal" '.strip')"
|
|
188
|
+
[ -n "$strip" ] && text="$(printf '%s' "$text" | RT_RE="$strip" perl -0777 -pe 's/$ENV{RT_RE}//gs' 2>/dev/null)"
|
|
189
|
+
|
|
190
|
+
has_re "$text" "$pattern" || continue
|
|
191
|
+
|
|
192
|
+
cancel="$(field "$signal" '.cancel')"
|
|
193
|
+
[ -n "$cancel" ] && has_re "$text" "$cancel" && continue
|
|
194
|
+
|
|
195
|
+
skip_signal=''
|
|
196
|
+
while IFS= read -r one; do
|
|
197
|
+
[ -z "$one" ] && continue
|
|
198
|
+
has_re "$text" "$one" || skip_signal=1
|
|
199
|
+
done <<ALL
|
|
200
|
+
$(printf '%s' "$signal" | jq -r '.all[]? // empty' 2>/dev/null)
|
|
201
|
+
ALL
|
|
202
|
+
[ -n "$skip_signal" ] && continue
|
|
203
|
+
|
|
204
|
+
found="${found}
|
|
205
|
+
- $(field "$signal" '.instead')"
|
|
206
|
+
done <<EOF
|
|
207
|
+
$(signals_json | jq -s -c 'reduce .[] as $one ({}; .[$one.key] = $one) | .[]' 2>/dev/null)
|
|
208
|
+
EOF
|
|
209
|
+
|
|
210
|
+
# Функция профиля остаётся вторым источником: деревья её уже написали. Поля читаются построчно,
|
|
211
|
+
# по тем же четырём колонкам, что объявлены выше.
|
|
212
|
+
while IFS= read -r line; do
|
|
213
|
+
[ -z "$line" ] && continue
|
|
214
|
+
signals_seen=1
|
|
215
|
+
scope="$(printf '%s' "$line" | cut -f1)"
|
|
216
|
+
pattern="$(printf '%s' "$line" | cut -f2)"
|
|
217
|
+
cancel="$(printf '%s' "$line" | cut -f3)"
|
|
218
|
+
replacement="$(printf '%s' "$line" | cut -f4)"
|
|
137
219
|
[ -z "$pattern" ] && continue
|
|
138
220
|
case "$scope" in
|
|
139
221
|
whole) text="$whole" ;;
|
|
@@ -147,6 +229,13 @@ done <<EOF
|
|
|
147
229
|
$(rt_reinvented_in "$path" 2>/dev/null)
|
|
148
230
|
EOF
|
|
149
231
|
|
|
232
|
+
# Гард без единого признака неотличим от гарда, которому нечего отбивать. Правку он пропускает —
|
|
233
|
+
# останавливать работу за ненастроенное дерево не за что, — но говорит, чем это настраивается.
|
|
234
|
+
if [ "$signals_seen" = 0 ]; then
|
|
235
|
+
printf '%s\n' 'reuse-first-guard: признаков нет — объявите наборы ключом `reuse.bundles` в настройке проверок' >&2
|
|
236
|
+
exit 0
|
|
237
|
+
fi
|
|
238
|
+
|
|
150
239
|
[ -z "$found" ] && exit 0
|
|
151
240
|
|
|
152
241
|
reason="BLOCKED: это уже написано. Файл: ${path##*/}
|
|
@@ -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
|
- Метка списка не поставлена при заведении: задача есть, а на доске её нет. Доска показывает
|
|
@@ -45,6 +45,36 @@ grep -rn "<похожий приём>" libs/admin libs/site --include='*.html' |
|
|
|
45
45
|
Спрашивается до того, как написан первый файл. То же относится к своей базе и к своему
|
|
46
46
|
инлайновому стилю.
|
|
47
47
|
|
|
48
|
+
## Своё готовое объявляется признаком
|
|
49
|
+
|
|
50
|
+
Заведённое с одобрения владельца видит только тот, кто о нём знает. Чтобы следующий его не
|
|
51
|
+
обошёл, дерево дописывает признак в свой файл признаков — тот, что назван ключом
|
|
52
|
+
`reuse.signals` в настройке проверок:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"key": "<короткое имя признака>",
|
|
57
|
+
"ext": ".ts",
|
|
58
|
+
"mode": "presence",
|
|
59
|
+
"scope": "whole",
|
|
60
|
+
"find": "implements +<интерфейс, который закрывает основа>",
|
|
61
|
+
"cancel": "extends +<основа>",
|
|
62
|
+
"instead": "<основа> — она уже держит <что именно>"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Область объявляется явно. `whole` читает правку вместе с содержимым файла и берётся там, где
|
|
67
|
+
признак судит устройство класса: наследование и метка объявлены один раз и в точечную правку не
|
|
68
|
+
попадают, поэтому признак без `whole` молчит всегда. `added` читает только добавленный текст и
|
|
69
|
+
берётся там, где признак судит саму строку — сырой тег, свой стиль.
|
|
70
|
+
|
|
71
|
+
Отмена `cancel` обязательна везде, где готовое можно позвать законно: без неё признак отбивает и
|
|
72
|
+
того, кто основу уже унаследовал. Пустой её не оставляют — признак без отмены объявляется без
|
|
73
|
+
этого поля вовсе.
|
|
74
|
+
|
|
75
|
+
Ключ, совпавший с пакетным, замещает его: дерево вправе сказать о своём готовом точнее, чем
|
|
76
|
+
пакет, который его не видел.
|
|
77
|
+
|
|
48
78
|
## Разовое отступление объявляется маркером
|
|
49
79
|
|
|
50
80
|
```html
|
|
@@ -48,8 +48,8 @@ docs/specs/<домен>/
|
|
|
48
48
|
процедуры домен обслуживает.
|
|
49
49
|
|
|
50
50
|
```markdown
|
|
51
|
-
**Зависимости:** `
|
|
52
|
-
**Законы:** `access`, `locales`, `
|
|
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
|
выглядит готовой к разбору.
|
|
@@ -46,9 +46,12 @@ description: Правило под «Закон о единообразии пр
|
|
|
46
46
|
раз в общем слое приложения, а экран её только применяет теми же директивами BEM.
|
|
47
47
|
- **Готовое расширяется, а не клонируется рядом.** Недостающий вариант заводится в ките или в
|
|
48
48
|
базовом классе, и его видят остальные экраны.
|
|
49
|
-
- **Накопленное до гарда сосчитано сплошной проверкой и в список только не растёт.** Признаки
|
|
50
|
-
|
|
51
|
-
остаётся числом в сводке.
|
|
49
|
+
- **Накопленное до гарда сосчитано сплошной проверкой и в список только не растёт.** Признаки у
|
|
50
|
+
неё те же, что у гарда, потому что оба читают одни и те же объявленные наборы, а смотрит она
|
|
51
|
+
файл целиком: гейт падает на новом месте, старое остаётся числом в сводке.
|
|
52
|
+
- **Признаки объявляются деревом, а не зашиты в проверку.** Дерево берёт из rt-tools не всё, и
|
|
53
|
+
признак о готовом из пакета, которого здесь нет, отвечает ложно ровно так же, как имя чужого
|
|
54
|
+
приложения.
|
|
52
55
|
|
|
53
56
|
## Чего из закона здесь нет
|
|
54
57
|
|
|
@@ -67,16 +70,24 @@ description: Правило под «Закон о единообразии пр
|
|
|
67
70
|
|
|
68
71
|
## Признаки, по которым видно, что готовое обошли
|
|
69
72
|
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
73
|
+
Списком их здесь нет: признак — это данные, а не текст правила и не код проверки. Наборы лежат
|
|
74
|
+
при пакете, по файлу на пакет rt-tools, и в каждом только то, что везёт он сам. Дерево называет
|
|
75
|
+
нужные ему наборы ключом `reuse.bundles` в настройке проверок и дописывает свои признаки файлом,
|
|
76
|
+
названным ключом `reuse.signals`; совпавший ключ замещает пакетный, новый дописывается. Гард на
|
|
77
|
+
правке и сплошная проверка читают отсюда оба — разойтись им нечем.
|
|
78
|
+
|
|
79
|
+
Что бывает признаком:
|
|
80
|
+
|
|
81
|
+
- нативный контрол в шаблоне там, где кит везёт свой;
|
|
82
|
+
- отказ, предупреждение или ожидание, собранные руками вместо готового;
|
|
83
|
+
- наложение поверх страницы, объявленное своими стилями, — подложка, порядок слоёв, вращение;
|
|
84
|
+
- раскладка, объявленная в файле стилей экрана, а не применённая директивами из общего слоя;
|
|
85
|
+
- своя реализация того, что даёт основа кита, вместо наследования;
|
|
86
|
+
- имя файла, повторяющее имя китового примитива, вне кита.
|
|
87
|
+
|
|
88
|
+
Признак называет свою область: наследование основы и метка класса в точечную правку не попадают,
|
|
89
|
+
и признак, судящий их по добавленному тексту, молчит всегда. Признак называет и отмену — образец,
|
|
90
|
+
при котором он не срабатывает: основа уже унаследована, готовое уже позвано.
|
|
80
91
|
|
|
81
92
|
## Ловушки
|
|
82
93
|
|
|
@@ -90,3 +101,10 @@ description: Правило под «Закон о единообразии пр
|
|
|
90
101
|
отступ, оставаясь тем же кодом.
|
|
91
102
|
- Ответ, данный до чтения образца, образец отменяет: согласованная форма выборки списка
|
|
92
103
|
переигрывалась вместе с контрактом через два вопроса после того, как была принята.
|
|
104
|
+
- **Набор объявляется по тому, что дерево потребляет, а не по тому, что пакет везёт.** Дерево, в
|
|
105
|
+
котором кит написан, а не позван, объявив его набор, получает советы звать кит на файлах самого
|
|
106
|
+
кита: признак верен, но обращён не туда. Такое дерево объявляет только те наборы, чьё готовое
|
|
107
|
+
оно берёт со стороны.
|
|
108
|
+
- **Гард, не получивший ни одного признака, неотличим от гарда, которому нечего отбивать.** Он
|
|
109
|
+
говорит об этом сам, и первая же правка в дереве без объявленных наборов это показывает.
|
|
110
|
+
Молчание проверки признаком порядка не считается — сначала смотрят, есть ли ей чем судить.
|
|
@@ -19,14 +19,15 @@ description: Переносимый слой правил агента — за
|
|
|
19
19
|
|
|
20
20
|
## Где что настраивается
|
|
21
21
|
|
|
22
|
-
| Что меняешь | Куда правка
|
|
23
|
-
| ---------------------------------------------- |
|
|
24
|
-
| какое правило гейт требует под какой файл | `.claude/rt-kit/gate-map.sh` — своя `skill_for`
|
|
25
|
-
| порты, адреса, линтеры, форма ветки, инвентарь | `.claude/rt-kit/project.sh` — свои `rt_*`
|
|
26
|
-
| пути и идентификаторы, которыми живут проверки | `.claude/rt-kit/checks.json`
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
22
|
+
| Что меняешь | Куда правка |
|
|
23
|
+
| ---------------------------------------------- | ------------------------------------------------------ |
|
|
24
|
+
| какое правило гейт требует под какой файл | `.claude/rt-kit/gate-map.sh` — своя `skill_for` |
|
|
25
|
+
| порты, адреса, линтеры, форма ветки, инвентарь | `.claude/rt-kit/project.sh` — свои `rt_*` |
|
|
26
|
+
| пути и идентификаторы, которыми живут проверки | `.claude/rt-kit/checks.json` |
|
|
27
|
+
| какие признаки единообразия дерево берёт | `checks.json`, ключи `reuse.bundles` и `reuse.signals` |
|
|
28
|
+
| раздел разложенного текста | `.claude/rt-kit/overrides/<идентификатор ресурса>` |
|
|
29
|
+
| что брать, а от чего отказаться | `.claude/rt-kit.json`, ключи `only` и `skip` |
|
|
30
|
+
| сам механизм — гард, проверка, текст правила | ресурс в пакете |
|
|
30
31
|
|
|
31
32
|
Надстройка объявляет функцию заново и вправе позвать умолчание тем же именем с суффиксом
|
|
32
33
|
`_default`. Слияние текста идёт по разделам `## `: совпавший заголовок замещает, новый
|
|
@@ -84,6 +85,10 @@ npx agent-kit propose # отправить предложения, адр
|
|
|
84
85
|
|
|
85
86
|
## Ловушки
|
|
86
87
|
|
|
88
|
+
- **Правила и паттерны при отвергнутом законе в отказе не перечисляются.** Их снимает каскад, а
|
|
89
|
+
строка на них становится выводимой: раскладка называет её лишней вместе с законом, из-за
|
|
90
|
+
которого она перестала снимать. Отказ мерит слой законов, а не число файлов в пакете.
|
|
91
|
+
|
|
87
92
|
- **Линтер по следам правки судит файл целиком, а не внесённую правку.** Импорт, добавленный
|
|
88
93
|
отдельным шагом, отбивается как неиспользуемый ещё до того, как появится строка, которая его
|
|
89
94
|
зовёт, и работа встаёт на половине. Правка делается одним вызовом либо в порядке «сначала
|
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
|
package/lib/assets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/assets.ts"],"names":[],"mappings":"AASA,OAAO,
|
|
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 {
|
|
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,
|
|
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
|
/** Кто требует — идентификатор выбранного ресурса. */
|