@rt-tools/agent-kit 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/hooks/claim-guard.sh +1 -0
- package/assets/hooks/conscience-guard.sh +1 -0
- package/assets/hooks/grill-gate.sh +2 -0
- package/assets/hooks/hook-input.sh +1 -0
- package/assets/hooks/postmortem-guard.sh +1 -0
- package/assets/hooks/proposal-guard.sh +8 -0
- package/assets/hooks/turn-exit-guard.sh +1 -0
- package/assets/hooks/waiting-turn-guard.sh +1 -0
- package/assets/hooks/work-start-guard.sh +2 -0
- package/assets/laws/frontend-application.md +10 -0
- package/assets/laws/work-conduct.md +3 -0
- package/assets/rules/git-workflow.azure.md +5 -0
- package/assets/rules/git-workflow.github.md +26 -23
- package/assets/rules/git-workflow.gitlab.md +5 -0
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.22.0.tgz +0 -0
- package/rt-tools-agent-kit-0.21.0.tgz +0 -0
|
@@ -85,6 +85,7 @@ fi
|
|
|
85
85
|
turn="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
86
86
|
def is_input:
|
|
87
87
|
.type == "user"
|
|
88
|
+
and ((.isCompactSummary // false) | not)
|
|
88
89
|
and (((.message.content // []) | if type == "array"
|
|
89
90
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
90
91
|
else 0 end) == 0);
|
|
@@ -50,6 +50,7 @@ transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/nu
|
|
|
50
50
|
verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
51
51
|
def is_input:
|
|
52
52
|
.type == "user"
|
|
53
|
+
and ((.isCompactSummary // false) | not)
|
|
53
54
|
and (((.message.content // []) | if type == "array"
|
|
54
55
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
55
56
|
else 0 end) == 0);
|
|
@@ -101,6 +101,7 @@ if command -v skill_for >/dev/null 2>&1 && [ -n "$rules_dir" ]; then
|
|
|
101
101
|
edited="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
102
102
|
def is_input:
|
|
103
103
|
.type == "user"
|
|
104
|
+
and ((.isCompactSummary // false) | not)
|
|
104
105
|
and (((.message.content // []) | if type == "array"
|
|
105
106
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
106
107
|
else 0 end) == 0);
|
|
@@ -133,6 +134,7 @@ fi
|
|
|
133
134
|
verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg re "$read_re" --arg tool "$tool" --arg need "$need_re" --arg rules "$rules_dir" '
|
|
134
135
|
def is_input:
|
|
135
136
|
.type == "user"
|
|
137
|
+
and ((.isCompactSummary // false) | not)
|
|
136
138
|
and (((.message.content // []) | if type == "array"
|
|
137
139
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
138
140
|
else 0 end) == 0);
|
|
@@ -95,6 +95,7 @@ rt_turn_has_text() {
|
|
|
95
95
|
got="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
96
96
|
def is_input:
|
|
97
97
|
.type == "user"
|
|
98
|
+
and ((.isCompactSummary // false) | not)
|
|
98
99
|
and (((.message.content // []) | if type == "array"
|
|
99
100
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
100
101
|
else 0 end) == 0);
|
|
@@ -69,6 +69,7 @@ admitted_re='был неправ|был не прав|ошибс|моя ошиб
|
|
|
69
69
|
verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg re "$admitted_re" '
|
|
70
70
|
def is_input:
|
|
71
71
|
.type == "user"
|
|
72
|
+
and ((.isCompactSummary // false) | not)
|
|
72
73
|
and (((.message.content // []) | if type == "array"
|
|
73
74
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
74
75
|
else 0 end) == 0);
|
|
@@ -63,10 +63,18 @@ context_re='пропозал|слою правил|слоя правил|сло
|
|
|
63
63
|
# Ход — это всё, что записано после последнего настоящего ввода владельца. Ответ инструмента
|
|
64
64
|
# приходит той же ролью, поэтому строки с `tool_result` вводом не считаются.
|
|
65
65
|
#
|
|
66
|
+
# Сводка сжатия — тоже не ввод, хотя приходит ролью владельца и ответом инструмента не является.
|
|
67
|
+
# Она пересказывает ходы, которые уже кончились, и просьба, исполненная вчера, читается в ней как
|
|
68
|
+
# сказанная сейчас: ход, где о предложениях не было сказано ни слова, отбивался на пересказе
|
|
69
|
+
# чужой просьбы — каталог предложений при этом был пуст, и отправлять было нечего вовсе. По
|
|
70
|
+
# словам сводка от речи владельца неотличима и богаче её, потому что пересказывает всю сессию
|
|
71
|
+
# разом; узнаётся она признаком записи, а не текстом.
|
|
72
|
+
#
|
|
66
73
|
# Хвост в 400 строк: запись хода растёт всю сессию, а судится только последний ход.
|
|
67
74
|
verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg asked "$asked_re" --arg ctx "$context_re" '
|
|
68
75
|
def is_input:
|
|
69
76
|
.type == "user"
|
|
77
|
+
and ((.isCompactSummary // false) | not)
|
|
70
78
|
and (((.message.content // []) | if type == "array"
|
|
71
79
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
72
80
|
else 0 end) == 0);
|
|
@@ -197,6 +197,7 @@ started_re='task:new|task:move|board\.mjs[[:space:]]+move|git[[:space:]]+checkou
|
|
|
197
197
|
verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg work "$work_re" --arg read "$read_re" --arg part "$part_re" --arg wait "$wait_re" --arg handover "$handover_re" --arg started "$started_re" '
|
|
198
198
|
def is_input:
|
|
199
199
|
.type == "user"
|
|
200
|
+
and ((.isCompactSummary // false) | not)
|
|
200
201
|
and (((.message.content // []) | if type == "array"
|
|
201
202
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
202
203
|
else 0 end) == 0);
|
|
@@ -102,6 +102,7 @@ verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r \
|
|
|
102
102
|
--arg read "$read_re" --arg red "$red_re" --arg ready "$ready_re" --arg vow "$vow_re" '
|
|
103
103
|
def is_input:
|
|
104
104
|
.type == "user"
|
|
105
|
+
and ((.isCompactSummary // false) | not)
|
|
105
106
|
and (((.message.content // []) | if type == "array"
|
|
106
107
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
107
108
|
else 0 end) == 0);
|
|
@@ -69,6 +69,7 @@ rt_needs rt_is_app_code work-start-guard || exit 0
|
|
|
69
69
|
asked="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
70
70
|
def is_input:
|
|
71
71
|
.type == "user"
|
|
72
|
+
and ((.isCompactSummary // false) | not)
|
|
72
73
|
and (((.message.content // []) | if type == "array"
|
|
73
74
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
74
75
|
else 0 end) == 0);
|
|
@@ -91,6 +92,7 @@ asked="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
|
91
92
|
edited="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r '
|
|
92
93
|
def is_input:
|
|
93
94
|
.type == "user"
|
|
95
|
+
and ((.isCompactSummary // false) | not)
|
|
94
96
|
and (((.message.content // []) | if type == "array"
|
|
95
97
|
then ([.[] | select(.type == "tool_result")] | length)
|
|
96
98
|
else 0 end) == 0);
|
|
@@ -26,6 +26,16 @@
|
|
|
26
26
|
рабочим и молча ничего не делает.
|
|
27
27
|
- **Набор записей приходит с сервера страницей, а не целиком.** Список, растущий вместе с
|
|
28
28
|
данными, однажды перестаёт открываться, и заметно это становится уже у пользователя.
|
|
29
|
+
- **У значения, положенного приложением в браузер, есть род: устройство либо вошедший.**
|
|
30
|
+
Хранилище браузера переживает и перезагрузку, и выход, и смену того, кто вошёл; род решает,
|
|
31
|
+
снимается ли значение при выходе. По имени ключа он не виден: язык интерфейса принадлежит
|
|
32
|
+
устройству, выбранная рабочая область — вошедшему, и по именам они неразличимы. Умолчания у
|
|
33
|
+
рода нет тоже: оставленное значение сеанса отдаёт следующему вошедшему чужой выбор, а снятая
|
|
34
|
+
настройка устройства заставляет выбирать язык при каждом входе. Значит род называет человек, и
|
|
35
|
+
называет до того, как ключ заведён.
|
|
36
|
+
- **Значения сеанса снимает то же место, которое снимает вход.** Уход по истёкшему входу идёт
|
|
37
|
+
мимо кнопки выхода, и ключ, снятый своим экраном, остаётся лежать — то есть достаётся
|
|
38
|
+
следующему вошедшему на этом устройстве.
|
|
29
39
|
- **Окружение, которого нет на сервере, приходит экрану извне, а не берётся у среды.**
|
|
30
40
|
Взятое напрямую, оно компилируется и падает при отдаче страницы сервером — то есть у гостя,
|
|
31
41
|
а не у того, кто это написал. Места, где иначе нельзя, названы поимённо.
|
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
просьбы, даже когда свой даёт тот же ответ: равноценность инструментов решает тот, кто просит.
|
|
56
56
|
Одинаковый результат равноценностью не является — у названного инструмента бывает видно то,
|
|
57
57
|
чего у заменителя нет вовсе.
|
|
58
|
+
- **Случившаяся подмена называется в том же докладе.** Чем сделано вместо названного и почему —
|
|
59
|
+
двумя словами, рядом с ответом на просьбу. Без этой строки владелец узнаёт о подмене, повторяя
|
|
60
|
+
указание: к той минуте работа по нему уже сделана не тем, и заплачено за неё дважды.
|
|
58
61
|
- **Понимание записано там, где идёт работа.** Оставленное в переписке живёт у одного участника и
|
|
59
62
|
до следующего дня; работу продолжает тот, у кого этой переписки нет.
|
|
60
63
|
- **Сказанное владельцем записывается его словами и задним числом не переписывается.** Пересказ
|
|
@@ -157,6 +157,11 @@ flowchart TD
|
|
|
157
157
|
только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
|
|
158
158
|
образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
|
|
159
159
|
выкатку.
|
|
160
|
+
- **На машине, где раннеров несколько, любой путь от домашнего каталога общий.** Умолчание
|
|
161
|
+
готового шага опасно именно тем, что оно общее: соседнее задание переписывает его под свою
|
|
162
|
+
версию, пока наше стоит между шагами. Каталог установки, имя контейнера и имя сборщика
|
|
163
|
+
называются поэтому по проекту и постоянно, а временный каталог решением не бывает — в нём
|
|
164
|
+
живёт хранилище пакетов.
|
|
160
165
|
- **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
|
|
161
166
|
красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
|
|
162
167
|
конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
|
|
@@ -168,6 +168,11 @@ flowchart TD
|
|
|
168
168
|
- **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
|
|
169
169
|
только импортированное тестом: ошибка типов в непокрытом коде доживает до сборки образа, то
|
|
170
170
|
есть до мержа.
|
|
171
|
+
- **На машине, где раннеров несколько, любой путь от домашнего каталога общий.** Умолчание
|
|
172
|
+
готового шага опасно именно тем, что оно общее: соседнее задание переписывает его под свою
|
|
173
|
+
версию, пока наше стоит между шагами. Каталог установки, имя контейнера и имя сборщика
|
|
174
|
+
называются поэтому по проекту и постоянно, а временный каталог решением не бывает — в нём
|
|
175
|
+
живёт хранилище пакетов.
|
|
171
176
|
- **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
|
|
172
177
|
красным. Шаг конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с
|
|
173
178
|
причиной, отбивает пуш, а не печатается рядом: предупреждение читается как разрешение.
|
|
@@ -217,35 +222,33 @@ flowchart TD
|
|
|
217
222
|
|
|
218
223
|
- **Автор PR не может быть его ревьювером.** Запрос разбора на себя GitHub принимает и молча не
|
|
219
224
|
создаёт: разбор выглядит запрошенным. Считаются только запрос и отзыв не от автора.
|
|
220
|
-
- **Вызов клиента хостинга идёт из дерева, а связка команд исхода не проверяет.**
|
|
221
|
-
клиент
|
|
222
|
-
|
|
223
|
-
- **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit
|
|
224
|
-
борде
|
|
225
|
+
- **Вызов клиента хостинга идёт из дерева, а связка команд исхода не проверяет.** Вне дерева
|
|
226
|
+
клиент отказывает, а следующее звено связки увозит на хостинг остаток отказавшего: тело
|
|
227
|
+
читается обратно тем же ходом.
|
|
228
|
+
- **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit`:** на старой
|
|
229
|
+
борде тот отвечает отказом про Projects.
|
|
225
230
|
- **Борда правится запросом GraphQL по идентификатору борды, а не по имени владельца.**
|
|
226
|
-
- **Почта машинного коммита копируется из компаньона, а не набирается по памяти.**
|
|
227
|
-
`<число>+<логин>@users.noreply.github.com`
|
|
231
|
+
- **Почта машинного коммита копируется из компаньона, а не набирается по памяти.** Адрес
|
|
232
|
+
`<число>+<логин>@users.noreply.github.com` сходится по числу: с чужим числом коммит уезжает
|
|
228
233
|
подписанным посторонним. Ту же строку держит профиль дерева, и гард отбивает пуш.
|
|
229
|
-
- **Личность машинной записи подтверждается ответом хостинга, а не узнаванием
|
|
230
|
-
|
|
231
|
-
- **Сценарии гардов задают настройки git сами, а не берут их с машины.**
|
|
232
|
-
|
|
233
|
-
|
|
234
|
+
- **Личность машинной записи подтверждается ответом хостинга, а не узнаванием строки:** её
|
|
235
|
+
спрашивают токеном, и логин с числом приходят вместе.
|
|
236
|
+
- **Сценарии гардов задают настройки git сами, а не берут их с машины.** Подпись с машины уводит
|
|
237
|
+
git в агент ключей, а заблокированный агент роняет весь набор: автор, почта и подпись идут
|
|
238
|
+
флагами `-c` прямо в команде.
|
|
234
239
|
|
|
235
240
|
- **Каждый коммит вклада ветки подписан машинной записью, и это проверяется набором пуша.** Гард
|
|
236
|
-
судит только коммит, назвавшийся
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
возврата.** Открытие и постановка ревьювера отвечают нулём и тогда, когда не сделали ничего.
|
|
241
|
+
судит только коммит, назвавшийся ею: подписанный человеком проходит мимо.
|
|
242
|
+
- **Состояние заявки перечитывается у хостинга сразу после публикации.** Открытие и постановка
|
|
243
|
+
ревьювера отвечают нулём и тогда, когда не сделали ничего.
|
|
240
244
|
- **Автор открытой заявки и наличие у неё ревьювера сверяются очередью работ.** До слияния оба
|
|
241
|
-
промаха не видны: заявка, открытая человеком, ревьювера не получит
|
|
242
|
-
заявка, которой его
|
|
243
|
-
- **Ревьюверы спрашиваются вызовом REST, а не выборкой клиента.** Её поля собирает GraphQL,
|
|
244
|
-
|
|
245
|
+
промаха не видны: заявка, открытая человеком, ревьювера не получит никогда — и выглядит как
|
|
246
|
+
заявка, которой его не поставили.
|
|
247
|
+
- **Ревьюверы спрашиваются вызовом REST, а не выборкой клиента.** Её поля собирает GraphQL, прав
|
|
248
|
+
на который у машинной записи нет: «сошлось» не отличить от «спросить было нечем».
|
|
245
249
|
|
|
246
|
-
- **Рабочее дерево не опустошается ради прогона инструмента.** Сравнение
|
|
247
|
-
|
|
248
|
-
дерева, ни сверка.
|
|
250
|
+
- **Рабочее дерево не опустошается ради прогона инструмента.** Сравнение идёт на второй копии:
|
|
251
|
+
прятанье уводит незакоммиченную работу туда, где её не видит ни состояние дерева, ни сверка.
|
|
249
252
|
|
|
250
253
|
## Чего из закона здесь нет
|
|
251
254
|
|
|
@@ -159,6 +159,11 @@ flowchart TD
|
|
|
159
159
|
только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
|
|
160
160
|
образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
|
|
161
161
|
выкатку.
|
|
162
|
+
- **На машине, где раннеров несколько, любой путь от домашнего каталога общий.** Умолчание
|
|
163
|
+
готового шага опасно именно тем, что оно общее: соседнее задание переписывает его под свою
|
|
164
|
+
версию, пока наше стоит между шагами. Каталог установки, имя контейнера и имя сборщика
|
|
165
|
+
называются поэтому по проекту и постоянно, а временный каталог решением не бывает — в нём
|
|
166
|
+
живёт хранилище пакетов.
|
|
162
167
|
- **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
|
|
163
168
|
красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
|
|
164
169
|
конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|