@rt-tools/agent-kit 0.22.0 → 0.23.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/checks/board-long-work.github.mjs +101 -0
- package/assets/checks/board-runs.github.mjs +34 -0
- package/assets/checks/check-board.github.mjs +16 -2
- package/assets/checks/check-reuse.mjs +4 -1
- package/assets/checks/check-schema-drift.mjs +65 -6
- package/assets/checks/rt-kit-checks.config.mjs +13 -0
- package/assets/checks/signals.mjs +41 -1
- package/assets/commands/next-session.md +16 -5
- package/assets/defaults/project.sh +16 -0
- package/assets/hooks/browser-guard-no-asking.sh +5 -1
- package/assets/hooks/git-guard-delivery.sh +15 -11
- package/assets/hooks/git-guard-push-tests.sh +22 -0
- package/assets/hooks/glossary-load.sh +23 -2
- package/assets/hooks/grill-gate.sh +62 -0
- package/assets/laws/autonomous-work.md +30 -0
- package/assets/laws/project-documentation.md +8 -0
- package/assets/patterns/autonomous-work-run.md +105 -0
- package/assets/patterns/browser-verification-stand.md +1 -1
- package/assets/patterns/doc-style-write.md +16 -0
- package/assets/patterns/git-workflow-pr-ready.md +93 -0
- package/assets/patterns/git-workflow-pr.azure.md +1 -1
- package/assets/patterns/git-workflow-pr.github.md +1 -1
- package/assets/patterns/git-workflow-pr.gitlab.md +1 -1
- package/assets/patterns/task-flow-start.md +47 -47
- package/assets/patterns/ts-procedure.md +3 -2
- package/assets/rules/autonomous-work.md +92 -0
- package/assets/rules/browser-verification.md +6 -0
- package/assets/rules/deploy-flow.azure.md +7 -0
- package/assets/rules/deploy-flow.github.md +7 -0
- package/assets/rules/deploy-flow.gitlab.md +7 -0
- package/assets/rules/doc-style.md +18 -0
- package/assets/rules/git-workflow.azure.md +8 -0
- package/assets/rules/git-workflow.github.md +44 -45
- package/assets/rules/git-workflow.gitlab.md +8 -0
- package/assets/rules/reuse-first.md +17 -3
- package/assets/rules/task-flow.md +62 -63
- package/assets/skills/agent-kit.md +20 -20
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +6 -0
- package/lib/commands.js.map +1 -1
- package/lib/push-gate.d.ts +14 -0
- package/lib/push-gate.d.ts.map +1 -0
- package/lib/push-gate.js +93 -0
- package/lib/push-gate.js.map +1 -0
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.23.0.tgz +0 -0
- package/assets/laws/application/access.md +0 -34
- package/assets/laws/application/locales.md +0 -33
- package/assets/laws/application/search-visibility.md +0 -24
- package/assets/patterns/permissions-procedure.md +0 -71
- package/assets/patterns/seo-page.md +0 -104
- package/assets/patterns/seo-verify.md +0 -83
- package/assets/patterns/translations-content.md +0 -107
- package/assets/patterns/translations-key.md +0 -64
- package/assets/rules/permissions.md +0 -116
- package/assets/rules/seo.md +0 -139
- package/assets/rules/translations.md +0 -96
- package/rt-tools-agent-kit-0.22.0.tgz +0 -0
|
@@ -165,6 +165,68 @@ verdict="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg re "$read_re"
|
|
|
165
165
|
| if ($asked_prose or $asking_now) and ($read | not) then "ask" else "pass" end
|
|
166
166
|
' 2>/dev/null)"
|
|
167
167
|
|
|
168
|
+
# Второй признак того же гарда: на этот вопрос владелец уже отвечал.
|
|
169
|
+
#
|
|
170
|
+
# Первый признак судит, читались ли правила, и на разрешённой работе молчит. А промах бывает
|
|
171
|
+
# другой: владелец дал указание прямой репликой, исполнитель нашёл факт, который меняет цену
|
|
172
|
+
# указания, но не его смысл, — и вместо строки о цене задал меню, где два варианта из трёх
|
|
173
|
+
# предлагали отменить решение владельца. Работа встала до ответа, разрешённая минутой раньше.
|
|
174
|
+
#
|
|
175
|
+
# Судится пересечение слов: вопрос, который сейчас уходит, против последней реплики владельца —
|
|
176
|
+
# и только там, где в записи уже был вызов инструмента вопроса, то есть владелец на вопрос
|
|
177
|
+
# отвечал. Понимания текста здесь нет и не нужно: три общих значимых слова означают тот же
|
|
178
|
+
# предмет, а разбор из шести вопросов идёт по разным предметам и порога не набирает.
|
|
179
|
+
#
|
|
180
|
+
# ОТКАЗ В ПОЛЬЗУ РАБОТЫ: нет вопроса в вызове, нет реплики владельца, нет прошлого вопроса —
|
|
181
|
+
# признак молчит.
|
|
182
|
+
if [ -n "$tool" ]; then
|
|
183
|
+
asked_json="$(printf '%s' "$input" | jq -r '(.tool_input.questions // []) | tostring' 2>/dev/null)"
|
|
184
|
+
seen="$(tail -n 400 "$transcript" 2>/dev/null | jq -s -r --arg now "$asked_json" '
|
|
185
|
+
def is_input:
|
|
186
|
+
.type == "user"
|
|
187
|
+
and ((.isCompactSummary // false) | not)
|
|
188
|
+
and (((.message.content // []) | if type == "array"
|
|
189
|
+
then ([.[] | select(.type == "tool_result")] | length)
|
|
190
|
+
else 0 end) == 0);
|
|
191
|
+
|
|
192
|
+
def words: [splits("[^\\p{L}\\p{N}]+")] | map(select(length >= 5)) | unique;
|
|
193
|
+
|
|
194
|
+
(map(is_input) | rindex(true)) as $i
|
|
195
|
+
| if $i == null then "нет" else
|
|
196
|
+
(.[$i] | (.message.content // []) | if type == "array"
|
|
197
|
+
then ([.[] | select(.type == "text") | .text] | join(" "))
|
|
198
|
+
else (. // "") end) as $said
|
|
199
|
+
| ([.[:$i][] | select(.type == "assistant") | (.message.content // [])[]
|
|
200
|
+
| select(.type == "tool_use") | select(.name == "AskUserQuestion")] | length) as $before
|
|
201
|
+
| if $before == 0 or ($said | length) == 0 then "нет" else
|
|
202
|
+
(($now | words) - (($now | words) - ($said | words))) as $common
|
|
203
|
+
| if ($common | length) >= 3 then "было" else "нет" end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
' 2>/dev/null)"
|
|
207
|
+
|
|
208
|
+
if [ "$seen" = "было" ]; then
|
|
209
|
+
reason="BLOCKED by grill-gate: на этот вопрос владелец уже отвечал в этом разговоре — продолжай работу, а не переспрашивай.
|
|
210
|
+
|
|
211
|
+
Указание владельца действует до его отмены. Новый факт против действующего указания — это строка в ответе о цене, а не новый вопрос: переспрашивают только то, чего указание не покрывает. Промах здесь не в форме вопроса, а в остановке работы, которая уже разрешена.
|
|
212
|
+
|
|
213
|
+
Вопрос всё-таки о другом предмете — назови в нём то, чего в прежнем ответе владельца нет: признак судит общие слова вопроса и последней реплики владельца, а не смысл."
|
|
214
|
+
|
|
215
|
+
# Общий хвост отказа: два законных хода и законная форма обхода, если она у отказа есть.
|
|
216
|
+
# shellcheck disable=SC1090
|
|
217
|
+
[ -f "$rt_hooks_dir/deny-tail.sh" ] && . "$rt_hooks_dir/deny-tail.sh" 2>/dev/null
|
|
218
|
+
command -v rt_deny_tail >/dev/null 2>&1 || rt_deny_tail() { :; }
|
|
219
|
+
deny_tail_text="$(rt_deny_tail "")"
|
|
220
|
+
[ -n "$deny_tail_text" ] && reason="${reason}
|
|
221
|
+
|
|
222
|
+
${deny_tail_text}"
|
|
223
|
+
|
|
224
|
+
jq -n --arg r "$reason" '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:$r}}' 2>/dev/null \
|
|
225
|
+
|| printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"grill-gate: на этот вопрос уже отвечали."}}\n'
|
|
226
|
+
exit 0
|
|
227
|
+
fi
|
|
228
|
+
fi
|
|
229
|
+
|
|
168
230
|
[ "$verdict" = "ask" ] || exit 0
|
|
169
231
|
|
|
170
232
|
if [ -n "$tool" ]; then
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Закон об автономном заходе
|
|
2
|
+
|
|
3
|
+
Заход, в котором владельца нет рядом. Он не отвечает на вопросы, не нажимает кнопок и не видит
|
|
4
|
+
работы до утра: всё, что исполнитель сделал за ночь, читается им разом и уже случившимся.
|
|
5
|
+
|
|
6
|
+
## Статьи
|
|
7
|
+
|
|
8
|
+
- **Автономный заход объявляет владелец, и кончается он его словом либо названной границей.**
|
|
9
|
+
Сам себя заход не продлевает: работа без конца — это работа, о которой владелец не просил.
|
|
10
|
+
- **Развилка закрывается умолчанием, а не ожиданием.** Вопрос, который некому задать, не
|
|
11
|
+
останавливает работу: исполнитель берёт умолчание, записывает его вместе с ценой ошибки и идёт
|
|
12
|
+
дальше. Стоящий заход не отвечает ни на один вопрос и стоит ровно столько же, сколько
|
|
13
|
+
отвеченный неверно.
|
|
14
|
+
- **Задача, упирающаяся в слово владельца, откладывается целиком.** Наполовину сделанная
|
|
15
|
+
выглядит сделанной: следующий заход читает её как закрытую и не возвращается к ней.
|
|
16
|
+
- **Действие, которое видно снаружи, в автономном заходе не делается.** Отправка чужой стороне,
|
|
17
|
+
публикация, слияние, письмо: их последствия отменяет человек, а его нет. Отмена стоит дороже
|
|
18
|
+
ожидания.
|
|
19
|
+
- **Работа, которую нечем подтвердить, не берётся.** Признак готовности автономного захода —
|
|
20
|
+
команда с известным выводом, а не взгляд исполнителя: подтвердить его некому.
|
|
21
|
+
- **Каждый шаг кончается следом на диске.** Заход обрывается без предупреждения — по окну, по
|
|
22
|
+
отказу, по сети, — и всё, что не записано, исчезает вместе с ним.
|
|
23
|
+
- **Работы идут чередой, а не веером из одного основания.** Каждая следующая ветвится от
|
|
24
|
+
предыдущей: расхождение тогда всплывает у того, у кого обе правки под рукой, а не у владельца,
|
|
25
|
+
у которого нет ни одной.
|
|
26
|
+
- **Заход кончается списком, а не итогом.** Владелец читает ночь целиком: по каждой работе видно,
|
|
27
|
+
что сделано, где лежит, чем подтверждено и чего она ждёт. Итог «сделано много» не говорит ни о
|
|
28
|
+
чём из четырёх.
|
|
29
|
+
- **Отказ стража автономный заход не кончает.** Он называет пропущенный шаг, и шаг делается;
|
|
30
|
+
заход, вставший на отказе до утра, теряет ночь целиком.
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
- **Число в тексте пересчитывается тем же изменением, которым пишется, и за этим тоже следит
|
|
44
44
|
автор.** Устаревшее число выглядит так же, как свежее, а машине их не различить: дата, версия и
|
|
45
45
|
номер — такие же числа, и проверка, которая знает один способ записи, на другом ошибается молча.
|
|
46
|
+
- **Слово, значащее в дереве что-то определённое, записано в словаре дерева.** Слова, которого
|
|
47
|
+
там нет, у читателя нет тоже: оно вводится в словарь тем же изменением, которым впервые
|
|
48
|
+
употреблено, либо заменяется тем, что уже есть. Словарь читается до того, как текст написан, а
|
|
49
|
+
не сверяется после: сверка после находит слово, вокруг которого уже построен абзац.
|
|
50
|
+
- **Документ, собираемый из нескольких источников, правится в источнике.** Правка собранного вида
|
|
51
|
+
живёт до следующей сборки и пропадает молча — а выглядит она ровно так же, как правка, которая
|
|
52
|
+
осталась. Собранный документ обязан называть свой источник в себе самом: сказанное о нём где-то
|
|
53
|
+
ещё до читателя может не доехать, а собранный вид доезжает всегда.
|
|
46
54
|
- **Отказ от слова распространяется на всё, что уже прочитано снаружи, а не только на файлы.**
|
|
47
55
|
Название работы, её описание и запись о правке живут вне дерева: поиск по файлам их не видит,
|
|
48
56
|
проверки текстов на них не смотрят, и отказ выглядит сделанным ровно до того, как читатель
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: autonomous-work-run
|
|
3
|
+
kind: pattern
|
|
4
|
+
rule: autonomous-work
|
|
5
|
+
description: Паттерн правила autonomous-work. Брать, когда владелец ушёл и работа идёт ночь напролёт — готовый цикл одной работы, ветвление чередой, запись умолчания вместо вопроса, список к утру, разбор отказа стража. Не брать для обычного хода работы — это паттерны task-flow-start и task-flow-resume.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Ночь без владельца
|
|
9
|
+
|
|
10
|
+
Паттерн правила `autonomous-work`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/autonomous-work.md`.
|
|
12
|
+
|
|
13
|
+
## Когда брать
|
|
14
|
+
|
|
15
|
+
- Владелец сказал, что уходит, и просил работать самостоятельно.
|
|
16
|
+
- За заход берётся больше одной задачи подряд, и отдать их наружу нельзя.
|
|
17
|
+
- Работа упёрлась в вопрос, а спросить некого.
|
|
18
|
+
|
|
19
|
+
## Череда веток
|
|
20
|
+
|
|
21
|
+
Первая работа ветвится от главной, каждая следующая — от предыдущей:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git checkout -b <КЛЮЧ>-<номер-1>-<slug> main # первая за ночь
|
|
25
|
+
git checkout -b <КЛЮЧ>-<номер-2>-<slug> <КЛЮЧ>-<номер-1>-<slug>
|
|
26
|
+
git checkout -b <КЛЮЧ>-<номер-3>-<slug> <КЛЮЧ>-<номер-2>-<slug>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Порядок вливания — снизу вверх, и он называется в списке к утру номерами. Ветка, заведённая от
|
|
30
|
+
главной посреди череды, столкнётся с соседкой в общих файлах — указателях, счётчиках, журналах —
|
|
31
|
+
и разбирать это будет владелец.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git log --oneline --graph --decorate main..HEAD | head -20 # чем стоит череда сейчас
|
|
35
|
+
git branch --list '<КЛЮЧ>-*' --format='%(refname:short) %(upstream:short)'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Цикл одной работы
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm run task:move -- <номер> in-progress # взята
|
|
42
|
+
git checkout -b <КЛЮЧ>-<номер>-<slug> <прошлая ветка> # череда, а не веер
|
|
43
|
+
cp -r docs/tasks/_template docs/tasks/<КЛЮЧ>-<номер>-<slug>
|
|
44
|
+
# разбор просьбы с умолчаниями, замысел, состояние «этап-идёт»
|
|
45
|
+
git add docs/tasks/<КЛЮЧ>-<номер>-<slug> && git commit # папка едет в историю сразу
|
|
46
|
+
# работа этапами: каждый кончается коммитом и прогоном признака готовности
|
|
47
|
+
# папка разбирается в описание прошлого последним коммитом
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Наружу за ночь не уходит ничего: ни `git push`, ни `gh pr create`, ни публикация, ни отметка
|
|
51
|
+
груза. Ветка остаётся местной, и утром владелец сам решает, что из неё отдавать.
|
|
52
|
+
|
|
53
|
+
## Умолчание вместо вопроса
|
|
54
|
+
|
|
55
|
+
Пишется в разбор просьбы, в раздел решений, — там же, где записался бы ответ владельца:
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
- **<что принято>** — <довод>. Спросить было некого: заход автономный. Цена ошибки:
|
|
59
|
+
<что придётся переделать, если владелец решит иначе>.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Цена ошибки — не вежливость, а признак: она отделяет умолчание, которое можно переиграть за
|
|
63
|
+
десять минут, от того, ради которого работу лучше отложить целиком.
|
|
64
|
+
|
|
65
|
+
## Отложенная задача
|
|
66
|
+
|
|
67
|
+
Задача, которой нужно слово владельца, не берётся: состояние на борде остаётся прежним, а в
|
|
68
|
+
список к утру идёт строка.
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
- **RT-<номер> — <заголовок>.** Отложена: <какой вопрос и почему умолчания у него нет>.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Список к утру
|
|
75
|
+
|
|
76
|
+
Дописывается по ходу, после каждой закрытой работы, а не собирается в конце.
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
| Работа | Ветка | Чем подтверждена | Чего ждёт |
|
|
80
|
+
| ------ | ----- | ---------------- | --------- |
|
|
81
|
+
| RT-… — <что сделано> | `<ветка>` (на `<предыдущей>`) | `<команда>` — <вывод> | заявки и слияния |
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Порядок строк — порядок вливания. Ниже списка — отложенные задачи с их вопросами.
|
|
85
|
+
|
|
86
|
+
## Отказ стража
|
|
87
|
+
|
|
88
|
+
Отказ называет пропущенный шаг: шаг делается, вызов повторяется, работа идёт дальше. Ночь
|
|
89
|
+
кончается работой, а не спором со стражем.
|
|
90
|
+
|
|
91
|
+
- Отказ требует того, что делать нельзя (пуш, заявка), — работа доводится до места, где
|
|
92
|
+
требование исполнимо утром, и уходит в список к утру строкой «ждёт заявки».
|
|
93
|
+
- Отказ повторяется на том же месте дважды — значит пропущенный шаг понят неверно: читается
|
|
94
|
+
правило, названное в отказе, а не переписывается формулировка.
|
|
95
|
+
|
|
96
|
+
## Частые промахи
|
|
97
|
+
|
|
98
|
+
- **Ветка заведена от главной по привычке.** Череда рвётся молча, и цена всплывает у владельца
|
|
99
|
+
на втором вливании.
|
|
100
|
+
- **Умолчание принято и не записано.** Утром оно неотличимо от знания, и владелец узнаёт о нём,
|
|
101
|
+
только когда работа сделана не так.
|
|
102
|
+
- **Задача взята и отложена наполовину.** На борде она в работе, в ветке — половина правки;
|
|
103
|
+
следующий заход читает её как начатую и не начинает заново.
|
|
104
|
+
- **Список к утру собран по памяти в последнюю минуту.** К этому часу окно уже сжималось, и
|
|
105
|
+
половина ночи в него не попала.
|
|
@@ -169,7 +169,7 @@ done
|
|
|
169
169
|
|
|
170
170
|
- **Одиночная сборка проекта серверы переживают, и отказываться от неё незачем.** Замерено
|
|
171
171
|
ответом до и после: все порты остались за своими процессами. Осторожность здесь стоит дороже
|
|
172
|
-
проверки —
|
|
172
|
+
проверки — целый набор проверок разметки остался незапущенным ровно потому, что сборку
|
|
173
173
|
сочли опасной, не замерив. Сборка из кэша замером не является: она не собирает вовсе, и видно
|
|
174
174
|
это по её длительности.
|
|
175
175
|
- Свой дев-сервер не поднимать: сайт на {{sitePort}}, админка на {{adminPort}}, API на {{apiPort}} уже подняты
|
|
@@ -104,6 +104,22 @@ description: Паттерн правила doc-style. Брать при напи
|
|
|
104
104
|
его вместе со смыслом. Считается это грепом по тексту, и число само по себе отказом не бывает:
|
|
105
105
|
судит его тот, кто правит следующим.
|
|
106
106
|
|
|
107
|
+
## Новое слово в словаре
|
|
108
|
+
|
|
109
|
+
Слово, значащее в дереве что-то определённое, живёт в словаре. Порядок — четыре шага, и первый
|
|
110
|
+
из них не пропускается: словарь читается до того, как текст написан, а не сверяется после.
|
|
111
|
+
|
|
112
|
+
1. **Поиск по собранному словарю целиком**, включая раздел отвергнутых слов. Слово, от которого
|
|
113
|
+
дерево отказалось, стоит там же — и вводить его заново значит отменять чужое решение молча.
|
|
114
|
+
2. **Выбор своего раздела.** Раздел надстройки замещает одноимённый раздел набора целиком:
|
|
115
|
+
название берётся такое, какого в наборе нет.
|
|
116
|
+
3. **Строка парой — слово и что это.** Без второй половины слово не введено: оно названо.
|
|
117
|
+
4. **Раскладка тем же изменением**, и сверка при этом зелёная. Слово, введённое в надстройку и не
|
|
118
|
+
разложенное, у читателя ещё не появилось.
|
|
119
|
+
|
|
120
|
+
Слово, от которого дерево отказывается, заводится там же и с заменой в той же строке: отказ без
|
|
121
|
+
замены исполнить нечем — пишущий видит запрет и не видит, чем его закрыть.
|
|
122
|
+
|
|
107
123
|
## Факт проверяется, а не вспоминается
|
|
108
124
|
|
|
109
125
|
Перед тем как написать, что код делает X, — открыть код и посмотреть. Пересказ по памяти
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-workflow-pr-ready
|
|
3
|
+
kind: pattern
|
|
4
|
+
rule: git-workflow
|
|
5
|
+
description: Паттерн правила git-workflow. Брать, когда заявки уже открыты: снятие черновика, разбор красного прогона, доведение череды до готовности, порядок «сначала довести отданное, потом брать новое». Открытие одной заявки — паттерн git-workflow-pr, порядок череды — git-workflow-stack.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Доведение заявки до готовности
|
|
9
|
+
|
|
10
|
+
Паттерн правила `git-workflow`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/delivery.md`. Открытие заявки — паттерн `git-workflow-pr`, порядок череды —
|
|
12
|
+
`git-workflow-stack`, разбор одного конфликта — `git-workflow-merge`.
|
|
13
|
+
|
|
14
|
+
## Когда брать
|
|
15
|
+
|
|
16
|
+
- Заявка открыта черновиком, и прогон по ней кончился.
|
|
17
|
+
- Открыто несколько заявок разом, и надо решить, что делать раньше — доводить их или брать
|
|
18
|
+
следующую задачу.
|
|
19
|
+
- Прогон заявки красный, а правка в ветке зелёная у себя.
|
|
20
|
+
|
|
21
|
+
## Черновик — состояние работы, а не её вид
|
|
22
|
+
|
|
23
|
+
Черновик говорит одно: работу нельзя вливать. Кнопка слияния у него заблокирована хостингом, и
|
|
24
|
+
владелец, открывший список, видит не «сделано», а «делается». Заявка с зелёным прогоном и
|
|
25
|
+
неснятым черновиком — сделанная работа, выглядящая незаконченной, и поправить это может только
|
|
26
|
+
тот, кто её отдал.
|
|
27
|
+
|
|
28
|
+
Отсюда порядок: **черновик снимается тем же ходом, которым прочитан зелёный прогон.** Не
|
|
29
|
+
следующим, не после соседней задачи.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
gh pr ready <номер>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Снятие черновика — последний шаг отдачи работы, а не отдельное дело. Пока он не сделан, работа
|
|
36
|
+
не отдана, сколько бы коммитов ни лежало в ветке.
|
|
37
|
+
|
|
38
|
+
## Сначала довести отданное, потом брать новое
|
|
39
|
+
|
|
40
|
+
Открытая заявка — работа в полёте: её прогон стареет, её ветка отстаёт от главной, её тело
|
|
41
|
+
описывает дерево на день написания. Всё это чинится дёшево сегодня и дорого через три задачи.
|
|
42
|
+
|
|
43
|
+
Очередь поэтому такая:
|
|
44
|
+
|
|
45
|
+
1. Прогоны открытых заявок прочитаны, черновики с зелёных сняты.
|
|
46
|
+
2. Красные разобраны и починены.
|
|
47
|
+
3. И только потом берётся следующая задача.
|
|
48
|
+
|
|
49
|
+
Взять новую задачу, оставив позади десяток заявок черновиками, — значит отчитаться о работе,
|
|
50
|
+
которой у владельца нет: он видит список «делается», а не список «готово».
|
|
51
|
+
|
|
52
|
+
## Состояние читается разом
|
|
53
|
+
|
|
54
|
+
Чем оно читается и как разбирается каждое поле — паттерн `git-workflow-freshness`; здесь
|
|
55
|
+
только то, что делают с прочитанным. Пустой прогон разбирается наравне с красным: у заявки
|
|
56
|
+
череды база не главная ветка, и фильтр по базе такое событие до конвейера не пропускает.
|
|
57
|
+
|
|
58
|
+
## Красный прогон разбирается по шагу, а не по заявке
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gh pr checks <номер>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Ответ называет упавший прогон и ссылку на него. Дальше у хостинга спрашивается имя упавшего
|
|
65
|
+
шага — `gh api` по этому прогону, отбором `select(.conclusion=="failure")` по его шагам.
|
|
66
|
+
|
|
67
|
+
Имя шага и есть диагноз. Правка идёт в ту ветку череды, где причина возникла, а не в ту, где
|
|
68
|
+
прогон покраснел: у череды красным становится всё, что стоит выше причины.
|
|
69
|
+
|
|
70
|
+
## Правка причины — в нижнюю ветку, оттуда волной вверх
|
|
71
|
+
|
|
72
|
+
Причина, общая для всей череды, чинится один раз в самой нижней ветке. Наверх она едет
|
|
73
|
+
вливанием, а не перебазированием: перебазирование переписывает историю уже отданных веток, и
|
|
74
|
+
хостинг закрывает заявки верхних как слитые, хотя в главной их правок нет.
|
|
75
|
+
|
|
76
|
+
Волна идёт снизу вверх, по одной ветке, и каждый шаг — три отдельных вызова: переключение на
|
|
77
|
+
следующую ветку череды, вливание предыдущей в неё, отправка. Одной строкой их не пишут: гард
|
|
78
|
+
поставки такую команду отбивает, и правильно — набор проверок гоняется по тому дереву, какое
|
|
79
|
+
лежит на момент разбора команды, то есть по прежней ветке.
|
|
80
|
+
|
|
81
|
+
Пропущенная посередине ветка оставляет свою заявку красной и ломает порядок вливания, поэтому
|
|
82
|
+
волна проходит череду целиком.
|
|
83
|
+
|
|
84
|
+
## Частые промахи
|
|
85
|
+
|
|
86
|
+
- Черновик не снят, потому что «ещё гоняется прогон». Прогон кончился час назад; читается его
|
|
87
|
+
состояние, а не память о том, что он шёл.
|
|
88
|
+
- Взята следующая задача, а десяток заявок остался черновиками. Для владельца сделанного нет.
|
|
89
|
+
- Красное чинится в той ветке, где покраснело. У череды это верхняя, а причина — в нижней, и
|
|
90
|
+
починка сверху оставляет красным всё под собой.
|
|
91
|
+
- Причина разослана по веткам перебазированием. Отданные ветки переписаны, заявки закрыты как
|
|
92
|
+
слитые, правок в главной нет.
|
|
93
|
+
- Пустой прогон принят за зелёный. Событие до конвейера не дошло, и заявка не проверена вовсе.
|
|
@@ -180,7 +180,7 @@ npm run task:move -- 86 in-review
|
|
|
180
180
|
8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
|
|
181
181
|
`browser-verification-measure`.
|
|
182
182
|
9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
|
|
183
|
-
|
|
183
|
+
правило видимости в поиске того дерева, где оно есть.
|
|
184
184
|
10. **PR привязан к рабочему элементу**, ревьювер и исполнитель стоят, а тело собрано по
|
|
185
185
|
образцу — разделы «Что сделано», «Чем подтверждено» и «Оставшийся шаг». Раздел оставшегося
|
|
186
186
|
шага к этому моменту говорит, что шагов не осталось: черновик снимается после разбора
|
|
@@ -242,7 +242,7 @@ npm run task:move -- 86 in-review
|
|
|
242
242
|
8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
|
|
243
243
|
`browser-verification-measure`.
|
|
244
244
|
9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
|
|
245
|
-
|
|
245
|
+
правило видимости в поиске того дерева, где оно есть.
|
|
246
246
|
10. **Тело PR собрано по образцу** — начинается строкой `Closes #<номер>`, несёт разделы «Что
|
|
247
247
|
сделано», «Чем подтверждено» и «Оставшийся шаг», а метки, ревьювер и исполнитель стоят.
|
|
248
248
|
Раздел оставшегося шага к этому моменту говорит, что шагов не осталось: черновик снимается
|
|
@@ -194,7 +194,7 @@ npm run task:move -- 86 in-review
|
|
|
194
194
|
8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
|
|
195
195
|
`browser-verification-measure`.
|
|
196
196
|
9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
|
|
197
|
-
|
|
197
|
+
правило видимости в поиске того дерева, где оно есть.
|
|
198
198
|
10. **Описание MR собрано по образцу** — начинается строкой `Closes #<номер>`, несёт разделы
|
|
199
199
|
«Что сделано», «Чем подтверждено» и «Оставшийся шаг», а метки, ревьювер и исполнитель
|
|
200
200
|
стоят. Раздел оставшегося шага к этому моменту говорит, что шагов не осталось: черновик
|
|
@@ -34,16 +34,15 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
|
|
|
34
34
|
|
|
35
35
|
Находки складываются в раздел «Что уже есть в дереве» разбора.
|
|
36
36
|
|
|
37
|
-
Дерево — не единственное место, где
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
ход работы, если касается одной.
|
|
37
|
+
Дерево — не единственное место, где лежит ответ. Решение прошлого захода, никуда не записанное,
|
|
38
|
+
живёт только в записи того захода: поиск по ним словом темы стоит одной команды. Найденное тем же
|
|
39
|
+
ходом переписывается в дерево — в замысел эпика, если связывает задачи, и в ход работы, если
|
|
40
|
+
касается одной.
|
|
42
41
|
|
|
43
|
-
Разведка, не нашедшая ничего, разрешением спрашивать не
|
|
44
|
-
искали, потом добираются места, которых в списке не
|
|
45
|
-
записи прошлых заходов.
|
|
46
|
-
|
|
42
|
+
Разведка, не нашедшая ничего, разрешением спрашивать не становится: сначала называется, где
|
|
43
|
+
искали, потом добираются места, которых в списке не было — замысел эпика, описание прошлого,
|
|
44
|
+
записи прошлых заходов. «В таком-то месте не нашёл» говорит о месте, а не о дереве, и вопрос
|
|
45
|
+
называет оба способа, которыми искали.
|
|
47
46
|
|
|
48
47
|
Разведка кончается не ощущением, а выводом команд. До первого вопроса владельцу исполнитель знает:
|
|
49
48
|
как устроен репозиторий (корневая памятка), что лежит в каталоге, о котором пойдёт речь (`ls`), и
|
|
@@ -52,11 +51,22 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
|
|
|
52
51
|
дереву не запускается ни одной команды.
|
|
53
52
|
|
|
54
53
|
Разведка по заведённой задаче кончается воспроизведённым симптомом, а не найденным файлом. Тело
|
|
55
|
-
задачи описывает дерево на день заведения, и
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
задачи описывает дерево на день заведения, и разведка по именам из тела подтверждает лишь то, что
|
|
55
|
+
файлы на месте: отпавшая задача от живой этим не отличается. Прежде первой правки разведка
|
|
56
|
+
повторяет то, на что задача жалуется, — зовёт процедуру, читает ответ, гоняет молчавшую
|
|
57
|
+
проверку; симптом не воспроизвёлся — задача закрывается отпавшей, и это законный исход.
|
|
58
|
+
|
|
59
|
+
Дерево, названное образцом, читается раскладкой целиком — обходом каталогов на два уровня, — и
|
|
60
|
+
только потом идут вопросы о приёмах. Ответ на «как здесь делают вот это» даёт одну папку, а
|
|
61
|
+
обобщённая до карты дерева она врёт: соседняя семья каталогов в неё не попадает, и пропажу
|
|
62
|
+
находит владелец.
|
|
63
|
+
|
|
64
|
+
Выведенное помечается прямо в списке, вместе с тем, чем его подтвердить. Догадка по соседнему
|
|
65
|
+
случаю стоит в одном списке с проверенным, и владелец читает список целиком как проверенный.
|
|
66
|
+
|
|
67
|
+
Шесть вопросов задаются за вычетом тех, на которые ответила разведка: вместо вопроса с готовым
|
|
68
|
+
ответом в разбор идёт строка «беру такой-то ответ, вот откуда». Признак один — есть ли ответ в
|
|
69
|
+
дереве; «задача кажется понятной» им не является ни в ту, ни в другую сторону.
|
|
60
70
|
|
|
61
71
|
**Следующее движение:** находки ложатся в разбор, и тем же ходом владельцу уходит первый из
|
|
62
72
|
шести вопросов. Разведка кончилась — состояние осталось прежним, ход тоже.
|
|
@@ -77,18 +87,14 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
|
|
|
77
87
|
| Чем будет видно, что задача закрыта | «работает» признаком не является |
|
|
78
88
|
| Есть ли образец, с которого снимается подход | разведка найдёт похожее, а не то |
|
|
79
89
|
|
|
80
|
-
Список шести — набор того, что
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Закрыть его можно и допущением, когда ответ очевиден: в разборе стоит строка «вопрос закрыт
|
|
87
|
-
допущением: <что принято>». Неверное допущение стоит правки, вопрос ради очевидного — захода.
|
|
90
|
+
Список шести — набор того, что закрыто к началу работы, а не набор реплик, которые надо
|
|
91
|
+
произнести. Вопрос, ответ на который владелец уже дал, отмечается закрытым вместе с тем, чем он
|
|
92
|
+
закрыт: ответ ищется в документации и в сказанном этим же заходом, включая исходную просьбу.
|
|
93
|
+
Закрыть его можно и допущением, когда ответ очевиден, — строкой «вопрос закрыт допущением:
|
|
94
|
+
<что принято>»: неверное допущение стоит правки, вопрос ради очевидного — захода.
|
|
88
95
|
|
|
89
96
|
Объём работы основанием для вопроса о границах не бывает: «это большая работа» решает
|
|
90
|
-
исполнитель, «делать ли её целиком» — владелец, и решает раньше, чем работа началась.
|
|
91
|
-
границах задаётся, когда владелец их не назвал, а не когда названные оказались широкими.
|
|
97
|
+
исполнитель, «делать ли её целиком» — владелец, и решает раньше, чем работа началась.
|
|
92
98
|
|
|
93
99
|
Форму вопроса задают настройки владельца: где требуют меню, спрашивается меню, и к каждому
|
|
94
100
|
вопросу добавляется свободный вариант — у закрытого набора нет строки «вопрос не тот».
|
|
@@ -135,16 +141,14 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
|
|
|
135
141
|
(`spec-critic`) → замысел и разбивка (`project-manager`). Пробелы, которые роли не смогли
|
|
136
142
|
закрыть, возвращаются владельцу — их относит главный агент.
|
|
137
143
|
|
|
138
|
-
Договорённость, вышедшая из конвейера, сверяется с `grill.md` построчно до
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
исполняется молча и не считается закрытой правкой текста.
|
|
144
|
+
Договорённость, вышедшая из конвейера, сверяется с `grill.md` построчно до работы по ней: роль
|
|
145
|
+
пишет текст, не видя владельца, и способна развернуть его ответ в противоположный — очередь
|
|
146
|
+
этапов оказывалась перевёрнутой, а входящие пункты переезжали в «не входит». Находка критика,
|
|
147
|
+
расходящаяся с ответом владельца, относится владельцу, а не исполняется молча.
|
|
143
148
|
|
|
144
|
-
Ход на этой границе не
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
исполнителя, и разницы между этими двумя случаями для конца хода нет.
|
|
149
|
+
Ход на этой границе не кончается: закрытый разбор выглядит законченным куском — ответы на диске,
|
|
150
|
+
файл закоммичен, отчитаться есть чем, — и отчёт встаёт на место договорённости. Пишется она тем
|
|
151
|
+
же ходом, конвейером ролей или рукой исполнителя.
|
|
148
152
|
|
|
149
153
|
**Следующее движение:** сверенная с разбором договорённость коммитится, и тем же ходом
|
|
150
154
|
заводятся задача, ветка и папка — а вышла из разбора серия, сперва объявляется эпик.
|
|
@@ -179,12 +183,10 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
|
|
|
179
183
|
таблицы, с меткой эпика. Выданные номера возвращаются в ту же таблицу — колонкой или приставкой
|
|
180
184
|
к названию, — и с этой минуты «взять следующую» отвечает номером, а не названием.
|
|
181
185
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
образца соседней задачи того же эпика, строка копировалась вместе с формой, а задача, заведённая
|
|
187
|
-
посреди работы находкой сверки, писалась не с образца.
|
|
186
|
+
Задача под эпиком называет его в своём теле — номер карточки и путь к замыслу одной строкой, — а
|
|
187
|
+
замысел называет задачу со своей стороны. Односторонняя привязка выглядит целой так же, как
|
|
188
|
+
двусторонняя: читатель приходит то от линии работ, то от карточки, и вторая сторона есть только
|
|
189
|
+
для одного из них.
|
|
188
190
|
|
|
189
191
|
**Следующее движение:** объявленный эпик коммитится вместе с номерами задач, и тем же ходом
|
|
190
192
|
берётся первая его задача — заведением ветки и папки.
|
|
@@ -197,19 +199,17 @@ git checkout -b <КЛЮЧ>-<номер>-<slug>
|
|
|
197
199
|
npm run task:move -- <номер> in-progress
|
|
198
200
|
```
|
|
199
201
|
|
|
200
|
-
Тело приходит файлом и пустым не бывает:
|
|
201
|
-
|
|
202
|
-
пустое молча, номером наравне с полным.
|
|
202
|
+
Тело приходит файлом и пустым не бывает: пустая задача не говорит ничего ни исполнителю, ни
|
|
203
|
+
владельцу, а дописать её потом можно только со слова владельца.
|
|
203
204
|
|
|
204
205
|
`task:new` переименовывает `_draft-<slug>` в `<КЛЮЧ>-<номер>-<slug>` и проставляет шапку замысла.
|
|
205
206
|
Ветка заводится вторым вызовом: составную «завести и сразу коммитить» гард главной ветки
|
|
206
207
|
отклоняет целиком.
|
|
207
208
|
|
|
208
|
-
Номер уже выдан — черновика нет и не заводится: папка открывается сразу под именем
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
разбора, а не про то, что с уже заведённой нельзя работать.
|
|
209
|
+
Номер уже выдан — черновика нет и не заводится: папка открывается сразу под именем ветки. Так
|
|
210
|
+
начинается половина работ: номер приходит прошлым заходом, замеченным дефектом или соседней
|
|
211
|
+
задачей, и переименовывать нечего. Ловушка «номер не бывает первым» сюда не относится — она про
|
|
212
|
+
то, что задачу не заводят до разбора.
|
|
213
213
|
|
|
214
214
|
Остальные два файла пишутся, а не кладутся образцом впрок: пустой `plan.md` неотличим от
|
|
215
215
|
замысла без этапов, а следующий заход доверяет папке задачи. Образец открывается тем же
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: ts-procedure
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: typescript-conventions
|
|
5
|
-
description: Паттерн правила typescript-conventions. Брать при заведении или правке процедуры Connect на бэкенде: готовый класс с полем метода и обработчиком, зависимости конструктором, имена файла и класса. Доступ к процедуре
|
|
5
|
+
description: Паттерн правила typescript-conventions. Брать при заведении или правке процедуры Connect на бэкенде: готовый класс с полем метода и обработчиком, зависимости конструктором, имена файла и класса. Доступ к процедуре описывает правило доступа того дерева, где оно есть.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Процедура Connect
|
|
@@ -41,7 +41,8 @@ export class PingProcedure implements IConnectProcedure<typeof HealthService.met
|
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Объявление доступа обязательно, и оно ровно
|
|
44
|
+
Объявление доступа обязательно, и оно ровно одно; чем оно объявляется, говорит правило
|
|
45
|
+
доступа того дерева, где такое правило есть.
|
|
45
46
|
|
|
46
47
|
## Почему форма такая
|
|
47
48
|
|