@rt-tools/agent-kit 0.23.0 → 0.24.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 +8 -2
- package/assets/checks/board.github.mjs +1 -1
- package/assets/checks/check-board.github.mjs +14 -0
- package/assets/checks/check-doc-paths.mjs +24 -5
- package/assets/checks/check-file-size.mjs +8 -2
- package/assets/checks/check-prose-style.mjs +10 -1
- package/assets/defaults/gate-map.sh +13 -0
- package/assets/defaults/project.sh +10 -0
- package/assets/defaults/shell.sh +18 -3
- package/assets/hooks/browser-guard-device-id.sh +42 -12
- package/assets/hooks/dispatch.sh +40 -9
- package/assets/hooks/docs-guard.sh +10 -0
- package/assets/hooks/exam-guard.sh +66 -16
- package/assets/hooks/git-guard-delivery-draft.sh +78 -0
- package/assets/hooks/git-guard-delivery.sh +49 -111
- package/assets/hooks/git-guard-main.sh +39 -4
- package/assets/hooks/git-guard-push-tests.sh +49 -3
- package/assets/hooks/hook-input.sh +17 -6
- package/assets/hooks/rule-source-guard.sh +11 -0
- package/assets/hooks/stand-login-guard.sh +101 -0
- package/assets/hooks/write-targets.sh +37 -4
- package/assets/laws/verifiability.md +12 -2
- package/assets/laws/work-conduct.md +59 -65
- package/assets/patterns/browser-verification-measure.md +41 -1
- package/assets/patterns/browser-verification-stand.md +56 -15
- package/assets/patterns/doc-style-human.md +75 -0
- package/assets/patterns/git-workflow-commit.azure.md +12 -0
- package/assets/patterns/git-workflow-commit.github.md +16 -3
- package/assets/patterns/git-workflow-commit.gitlab.md +12 -0
- package/assets/patterns/git-workflow-merge.md +8 -0
- package/assets/patterns/task-flow-start.md +1 -1
- package/assets/patterns/testing-e2e.md +18 -8
- package/assets/pitfalls/task-flow.md +40 -40
- package/assets/rules/browser-verification.md +29 -3
- package/assets/rules/doc-style.md +36 -0
- package/assets/rules/git-workflow.github.md +20 -23
- package/assets/rules/reuse-first.md +8 -2
- package/assets/rules/styling-bem.md +8 -1
- package/assets/rules/task-flow.md +73 -73
- package/assets/rules/testing.md +21 -0
- package/assets/skills/agent-kit.md +60 -70
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +63 -2
- package/lib/commands.js.map +1 -1
- package/lib/enroll.d.ts.map +1 -1
- package/lib/enroll.js +1 -1
- package/lib/enroll.js.map +1 -1
- package/lib/observations.d.ts +10 -1
- package/lib/observations.d.ts.map +1 -1
- package/lib/observations.js +1 -0
- package/lib/observations.js.map +1 -1
- package/lib/override-marks.d.ts +24 -0
- package/lib/override-marks.d.ts.map +1 -0
- package/lib/override-marks.js +98 -0
- package/lib/override-marks.js.map +1 -0
- package/lib/shipment.d.ts.map +1 -1
- package/lib/shipment.js +1 -1
- package/lib/shipment.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.24.0.tgz +0 -0
- package/rt-tools-agent-kit-0.23.0.tgz +0 -0
|
@@ -17,15 +17,26 @@ description: Паттерн правила browser-verification. Брать, к
|
|
|
17
17
|
- Порт отвечает не тем, чего ждали.
|
|
18
18
|
- Нужен вход в админку.
|
|
19
19
|
|
|
20
|
+
## Номера портов объявляет дерево, а не паттерн
|
|
21
|
+
|
|
22
|
+
Команды ниже называют порты именами — `API_PORT`, `SITE_PORT`, `ADMIN_PORT`, `SSR_PORT`, порты
|
|
23
|
+
стенда и порты прокси. Номеров у паттерна нет: раскладка стендов у каждого дерева своя, а дерево с
|
|
24
|
+
одним приложением, обязанное назвать восемь чужих номеров, называет их выдуманными — и
|
|
25
|
+
подстановки теряют смысл. Номера дерево объявляет своим профилем: в переменных окружения либо
|
|
26
|
+
разделом надстройки при этом паттерне, где стоят его же готовые команды с именами целей раннера.
|
|
27
|
+
|
|
28
|
+
Роль каждого имени — то, о чём говорит проза: порт приёмника, порт сайта, порт админки, порт
|
|
29
|
+
сервера отрисовки. Дерево, у которого такого приложения нет, эти разделы не читает.
|
|
30
|
+
|
|
20
31
|
## Сначала — что отвечает на порту
|
|
21
32
|
|
|
22
33
|
До первого запроса, а не после непонятного ответа:
|
|
23
34
|
|
|
24
35
|
```bash
|
|
25
|
-
lsof -nP -iTCP
|
|
36
|
+
lsof -nP -iTCP:$API_PORT -sTCP:LISTEN
|
|
26
37
|
```
|
|
27
38
|
|
|
28
|
-
На
|
|
39
|
+
На порту приёмника регулярно висит собранный артефакт из прошлой сессии
|
|
29
40
|
(`node -r dotenv/config dist/apps/api/main.js`): он отвечает 200 старым кодом, а процедуры,
|
|
30
41
|
заведённой в ветке, у него нет вовсе. Таких процессов бывает несколько, и снимать надо все —
|
|
31
42
|
по PID из `lsof`, каждый: `pkill` по шаблону `nx serve api` не попадает ни в один.
|
|
@@ -34,7 +45,7 @@ lsof -nP -iTCP:{{apiPort}} -sTCP:LISTEN
|
|
|
34
45
|
|
|
35
46
|
```bash
|
|
36
47
|
npx nx build site
|
|
37
|
-
PORT
|
|
48
|
+
PORT=$SITE_STAND_PORT node dist/apps/site/server/server.mjs
|
|
38
49
|
```
|
|
39
50
|
|
|
40
51
|
Это не дев-сервер: гард ловит `nx|ng serve`, пакетные раннеры и статические серверы, а запуск
|
|
@@ -72,17 +83,32 @@ Angular DevTools, нужна ещё и dev-конфигурация (`--configur
|
|
|
72
83
|
человеку набрать пароль, открыть вкладку или нажать кнопку означает неверно выбранный путь, а
|
|
73
84
|
не нехватку прав у исполнителя.
|
|
74
85
|
|
|
86
|
+
**Спрашивают режим работы, а не ввод.** Ввод в поле пароля отбивает классификатор
|
|
87
|
+
автоматического режима: он судит само действие и адресов не различает — стенд на местном порту
|
|
88
|
+
выглядит для него боевым сайтом. Ход отсюда один: назвать владельцу отбитое действие, попросить
|
|
89
|
+
обычный режим, заполнить форму парой засева самому и вернуться в автоматический режим. Просьба
|
|
90
|
+
«войди сам» и «введи пароль» перекладывает на владельца работу агента и выглядит законной ровно
|
|
91
|
+
потому, что перед ней стоит настоящее препятствие: отбитое поле, чужое расширение в браузере,
|
|
92
|
+
отключившийся профиль. Препятствие остаётся препятствием агента.
|
|
93
|
+
|
|
94
|
+
Пути, которыми препятствие снимается своими силами, — до всякой просьбы: подстановка значения
|
|
95
|
+
инструментом формы по ссылке на элемент, выключение мешающего расширения в профиле браузера,
|
|
96
|
+
подъём стенда на другом адресе. Второй драйвер полем пароля не оправдывается: он заполняет то же
|
|
97
|
+
поле без классификатора, но обойдённый запрет снимается не с одного поля, а со всех сразу.
|
|
98
|
+
Оставленный обычный режим снимает подтверждение и со всех последующих действий захода, поэтому
|
|
99
|
+
возврат — часть входа, а не отдельная уборка.
|
|
100
|
+
|
|
75
101
|
Стенд владельца запасным путём не бывает: он собирает главную ветку и о правке в рабочем дереве
|
|
76
102
|
не говорит ничего.
|
|
77
103
|
|
|
78
104
|
## Стенд API
|
|
79
105
|
|
|
80
|
-
Собранный артефакт поднимается на свободном порту, а не на
|
|
106
|
+
Собранный артефакт поднимается на свободном порту, а не на порту приёмника: там отвечает приёмник
|
|
81
107
|
владельца, и окружение у него не то, которое проверяется.
|
|
82
108
|
|
|
83
109
|
```bash
|
|
84
110
|
npx nx build api
|
|
85
|
-
env -u JWT_SECRET NODE_ENV=production API_PORT
|
|
111
|
+
env -u JWT_SECRET NODE_ENV=production API_PORT=$API_STAND_PORT DATABASE_URL=… node dist/apps/api/main.js
|
|
86
112
|
```
|
|
87
113
|
|
|
88
114
|
Переменные окружения задаются в самой команде, по одной на проверяемый случай. Отказ на
|
|
@@ -92,7 +118,7 @@ env -u JWT_SECRET NODE_ENV=production API_PORT={{prodApiPort}} DATABASE_URL=…
|
|
|
92
118
|
Процедура зовётся полным именем, как её объявляет контракт:
|
|
93
119
|
|
|
94
120
|
```bash
|
|
95
|
-
curl -sS -X POST http://localhost
|
|
121
|
+
curl -sS -X POST http://localhost:$API_STAND_PORT/<область>.v1.AuthService/GetMe \
|
|
96
122
|
-H 'content-type: application/json' -H "authorization: Bearer $TOKEN" -d '{}'
|
|
97
123
|
```
|
|
98
124
|
|
|
@@ -108,7 +134,7 @@ curl -sS -X POST http://localhost:{{prodApiPort}}/<область>.v1.AuthServic
|
|
|
108
134
|
```bash
|
|
109
135
|
docker run -d --name <префикс>-stand-nginx \
|
|
110
136
|
--add-host api:host-gateway --add-host ssr:host-gateway \
|
|
111
|
-
-p
|
|
137
|
+
-p $PROXY_SITE_PORT:80 -p $PROXY_ADMIN_PORT:8081 \
|
|
112
138
|
-v "$PWD/deploy/nginx/main.conf:/etc/nginx/nginx.conf:ro" \
|
|
113
139
|
-v "$PWD/deploy:/etc/nginx/conf.d:ro" \
|
|
114
140
|
-v "$PWD/dist/apps/admin/browser:/usr/share/nginx/html/admin:ro" \
|
|
@@ -126,9 +152,24 @@ docker run -d --name <префикс>-stand-nginx \
|
|
|
126
152
|
тем же, чем и на свой. За настоящим прокси запросы идут со своим заголовком ровно потому, что
|
|
127
153
|
прокси стоит перед дев-сервером, — оттуда и `-H "Host: localhost"`.
|
|
128
154
|
- Переменные окружения стенда обязаны смотреть на процессы стенда. `CACHE_REFRESH_URL`,
|
|
129
|
-
направленный на
|
|
155
|
+
направленный на порт сайта, сбрасывает кэш мимо того процесса, который держит справочник
|
|
130
156
|
перенаправлений в памяти, — исправный механизм при этом выглядит сломанным.
|
|
131
157
|
|
|
158
|
+
## Стенд живёт ровно столько, сколько проверка
|
|
159
|
+
|
|
160
|
+
Стенд поднят под один вывод и после него не нужен. Брошенный не мешает ничему и не подаёт сигнала:
|
|
161
|
+
имя у него своё, порт свободный, места он почти не занимает — увидеть его можно только вызовом
|
|
162
|
+
списка, а звать его незачем. Разбирать накопленное поэтому приходится человеку, и отличить
|
|
163
|
+
брошенный от живого стенда соседнего дерева он по имени не может.
|
|
164
|
+
|
|
165
|
+
Снос идёт тем же ходом, которым сделан вывод:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
docker rm -f <имя стенда>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Имя даётся по номеру задачи — так видно, чей стенд остался, если ход всё-таки оборвался.
|
|
172
|
+
|
|
132
173
|
## Дерево для сравнения
|
|
133
174
|
|
|
134
175
|
Сказать «это сломала правка» можно, только если видно, что до правки было иначе. Проверяют это
|
|
@@ -142,8 +183,8 @@ pnpm install --frozen-lockfile # из ../<префикс>-base: node_mod
|
|
|
142
183
|
- Для сравнения берут не главную ветку, а последний коммит, на котором дерево собирается:
|
|
143
184
|
главная бывает сломана, и тогда «до» и «после» различаются не из-за правки. Собирается ли
|
|
144
185
|
коммит — проверяют сборкой, а не тем, что он в главной ветке.
|
|
145
|
-
- Стенд второго дерева поднимают на своих портах:
|
|
146
|
-
занимать нельзя — стенд разработчика ходит по имени `ssr
|
|
186
|
+
- Стенд второго дерева поднимают на своих портах: порты сайта, админки и приёмника заняты владельцем, а порт отрисовки
|
|
187
|
+
занимать нельзя — стенд разработчика ходит по имени `ssr:<порт отрисовки>`.
|
|
147
188
|
- Оба стенда держат поднятыми одновременно — ровно до конца сравнения: если сравнивать по памяти
|
|
148
189
|
между двумя запусками, заметишь только то, что успел запомнить. Со сравнением стенд второго
|
|
149
190
|
дерева гасится тем же ходом, а не оставляется до конца захода: оставленные стенды копятся
|
|
@@ -157,7 +198,7 @@ pnpm install --frozen-lockfile # из ../<префикс>-base: node_mod
|
|
|
157
198
|
приписать своей сборке, ни снять с неё подозрение.
|
|
158
199
|
|
|
159
200
|
```bash
|
|
160
|
-
for u in http://localhost
|
|
201
|
+
for u in http://localhost:$API_PORT/health http://localhost:$SITE_PORT/ http://localhost:$ADMIN_PORT/; do
|
|
161
202
|
printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "$u")" "$u"
|
|
162
203
|
done
|
|
163
204
|
```
|
|
@@ -170,9 +211,9 @@ done
|
|
|
170
211
|
- **Одиночная сборка проекта серверы переживают, и отказываться от неё незачем.** Замерено
|
|
171
212
|
ответом до и после: все порты остались за своими процессами. Осторожность здесь стоит дороже
|
|
172
213
|
проверки — целый набор проверок разметки остался незапущенным ровно потому, что сборку
|
|
173
|
-
сочли опасной, не замерив. Сборка из кэша замером не
|
|
214
|
+
сочли опасной, не замерив. Сборка из кэша замером не бывает: она не собирает вовсе, и видно
|
|
174
215
|
это по её длительности.
|
|
175
|
-
- Свой дев-сервер не поднимать:
|
|
216
|
+
- Свой дев-сервер не поднимать: сайт, админка и приёмник уже подняты
|
|
176
217
|
владельцем, и второй экземпляр отбивается гардом.
|
|
177
218
|
- **Отбитый статический сервер читается как запрет проверки, а он указание на верный ход.**
|
|
178
219
|
Отдавать собранное им нельзя не из осторожности: приложение ходит на свой origin, а глубокая
|
|
@@ -184,8 +225,8 @@ done
|
|
|
184
225
|
поднятый дев-сервер годится, чтобы понять, что происходит на незнакомом экране, и не годится
|
|
185
226
|
подтверждением: подтверждение — замер на стенде из прод-сборки.
|
|
186
227
|
- **Общая сборка глушит все три дев-сервера владельца, а не только API.** После
|
|
187
|
-
`nx run-many -t build` ложатся и
|
|
228
|
+
`nx run-many -t build` ложатся и сайт, и админка. Собирать надо то, что
|
|
188
229
|
проверяешь (`npx nx build site`), а не всё дерево. Если серверы легли, поднять их обратно
|
|
189
230
|
агент не может — мешает гард, поэтому владельцу говорят об этом сразу, а не в конце сессии.
|
|
190
|
-
- Порт
|
|
231
|
+
- Порт отрисовки занимать осторожно: стенд разработчика ходит по тому же имени `ssr:<порт отрисовки>`
|
|
191
232
|
через `host-gateway`, и пока на нём висит чужой процесс, стенд отдаёт чужую сборку.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-style-human
|
|
3
|
+
kind: pattern
|
|
4
|
+
rule: doc-style
|
|
5
|
+
description: Паттерн правила doc-style. Брать при написании задачи в очереди работ, описания заявки и ответа владельцу в чате. Образцы «так» и «не так» на каждый из трёх текстов и разбор слов, которые в них заменяются. Форму ответа о состоянии работы называет правило status-report.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Задача, описание заявки и ответ владельцу
|
|
9
|
+
|
|
10
|
+
Паттерн правила `doc-style`. Три текста читает человек со стороны: он помнит продукт и не
|
|
11
|
+
читал ни одного правила слоя. Здесь — как они пишутся; что при этом должно быть верно, говорит
|
|
12
|
+
раздел «Тексты для человека» самого правила.
|
|
13
|
+
|
|
14
|
+
## Когда брать
|
|
15
|
+
|
|
16
|
+
- Заводится задача в очереди работ.
|
|
17
|
+
- Пишется описание заявки на слияние.
|
|
18
|
+
- Пишется ответ владельцу в чате — кроме ответа о состоянии работы: его форму называет правило
|
|
19
|
+
`status-report`.
|
|
20
|
+
|
|
21
|
+
## Слова, которые заменяются
|
|
22
|
+
|
|
23
|
+
Левая колонка — слова слоя правил. Они верны внутри слоя и пусты для того, кто в него не
|
|
24
|
+
заглядывает.
|
|
25
|
+
|
|
26
|
+
| Слово слоя | Чем сказать владельцу |
|
|
27
|
+
| ------------------ | ---------------------------------------------------------- |
|
|
28
|
+
| заявка на слияние | правка, которая ждёт вашего слова |
|
|
29
|
+
| прогон, набор | проверки; «проверки прошли», «проверки красные» |
|
|
30
|
+
| гард, гейт | что именно не пустило и почему |
|
|
31
|
+
| договорённость | о чём договорились по этому экрану |
|
|
32
|
+
| объём правки | что меняется на экране и где |
|
|
33
|
+
| раскладка ресурсов | обновление правил на машине |
|
|
34
|
+
|
|
35
|
+
## Задача
|
|
36
|
+
|
|
37
|
+
Заголовок называет предмет, тело — что человек не может сделать. Красная проверка стоит в теле
|
|
38
|
+
последней строкой: она говорит, где смотреть, и не говорит, зачем чинить.
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
✗ Сквозная спека берёт пункт заглушкой, а прогон на вершине не доходит до выкатки
|
|
42
|
+
✓ Раздел «Отчёты» не открывается у пользователя, и из-за этого не идёт выкатка.
|
|
43
|
+
Красная проверка — сквозной набор, шаг «отчёты».
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Описание заявки
|
|
47
|
+
|
|
48
|
+
Первый абзац — что меняется для человека. Дальше — чем это подтверждено. Имена файлов уместны
|
|
49
|
+
в конце, а не вместо первого абзаца.
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
✗ Ярус личности вызова получил второй признак, набор гейта зелёный
|
|
53
|
+
✓ Заявки от машинной записи больше не открываются от имени владельца: теперь перед открытием
|
|
54
|
+
спрашивается, кто приходит по токену. Проверки прошли, 26 сценариев.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Ответ в чате
|
|
58
|
+
|
|
59
|
+
Отвечает на заданный вопрос первым предложением. Утверждение о дереве идёт вместе с командой и
|
|
60
|
+
её выводом — этого требует правило `status-report`, и в чате оно верно так же.
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
✗ Работа отдана, красное въехало в главную, откат прикрыт гардом
|
|
64
|
+
✓ Правку я отправил, она ждёт вашего слова. В главной ветке сейчас красный шаг «сборка витрины»
|
|
65
|
+
— упал не на этой правке, вывод: 76 из 76 сценариев не поднялись, витрина лежит.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Ловушки
|
|
69
|
+
|
|
70
|
+
- **Короче не значит понятнее.** Текст словами слоя выходит на треть короче и бесполезен тому,
|
|
71
|
+
кто решает, срочная это работа или нет.
|
|
72
|
+
- **«Не X, а Y» выглядит объяснением и ничего не объясняет.** Владелец узнаёт, чего не было, и
|
|
73
|
+
не узнаёт, что есть.
|
|
74
|
+
- **Слово «готово» без числа читается как проверенный факт.** Число — номер прогона, сколько
|
|
75
|
+
сценариев из скольких, время проверки.
|
|
@@ -25,6 +25,13 @@ description: Паттерн правила git-workflow. Брать на зав
|
|
|
25
25
|
|
|
26
26
|
Все четыре делает одна команда дерева, а не рука: делить их значит забывать последний.
|
|
27
27
|
|
|
28
|
+
**Команду, которой нет, паттерн не заменяет вызовами клиента.** Дерево, взявшее пакет впервые,
|
|
29
|
+
получает файлы проверок, но не записи о них в своём манифесте: раскладка правит ресурсы, а
|
|
30
|
+
манифест потребителя ей не принадлежит. Ходов отсюда два: завести команду тем же ходом либо
|
|
31
|
+
повторить все её шаги поимённо по перечню выше. Обход вызовами клиента выглядит исполнением до
|
|
32
|
+
последнего шага перечня: он забывается первым, потому что предыдущие уже дали видимый
|
|
33
|
+
результат.
|
|
34
|
+
|
|
28
35
|
```bash
|
|
29
36
|
npm run task:new -- --title 'Письма владельцу не уходят молча' \
|
|
30
37
|
--type Bug --area '<проект>\<команда>' --slug mail-owner-silence < описание.md
|
|
@@ -151,6 +158,11 @@ Docs-skip: правка только в тестах хука, зеркала у
|
|
|
151
158
|
|
|
152
159
|
## Частые промахи
|
|
153
160
|
|
|
161
|
+
- **Сверка сразу после добавления отвечает «нет», когда карточка уже стоит.** Очередь работ отдаёт
|
|
162
|
+
новый элемент не в ту же секунду, в какую его завели, а последний шаг читает её следующим
|
|
163
|
+
вызовом. Ответ на это — перечитать очередь целиком, а не завести карточку второй раз: две записи
|
|
164
|
+
об одной задаче снимает только администратор. Сама команда заведения при этом требует правки:
|
|
165
|
+
состояние читается сразу за мутацией, без повтора, и ложный отказ здесь дороже задержки.
|
|
154
166
|
- Область и итерация не заданы: элемент заведён, но на доску команды не попал.
|
|
155
167
|
- Состояние взято не из процесса проекта: перевод отвечает отказом на каждой задаче, и это
|
|
156
168
|
читается как сломанная команда, а не как неверное имя состояния.
|
|
@@ -26,6 +26,14 @@ description: Паттерн правила git-workflow. Брать на зав
|
|
|
26
26
|
|
|
27
27
|
Все четыре шага делает одна команда дерева, а не рука: делить их значит забывать третий.
|
|
28
28
|
|
|
29
|
+
**Команду, которой нет, паттерн не заменяет вызовами клиента.** Дерево, взявшее пакет впервые,
|
|
30
|
+
получает файлы проверок, но не записи о них в своём манифесте: раскладка правит ресурсы, а
|
|
31
|
+
манифест потребителя ей не принадлежит. Ходов отсюда два: завести команду тем же ходом либо
|
|
32
|
+
повторить все её шаги поимённо по перечню выше. Обход вызовами клиента выглядит исполнением до
|
|
33
|
+
последнего шага перечня: он забывается первым, потому что предыдущие уже дали видимый
|
|
34
|
+
результат. Так карточка простояла вне
|
|
35
|
+
колонок всю работу — два коммита и два закрытых этапа.
|
|
36
|
+
|
|
29
37
|
**Локальные ветки этой задачи читаются до заведения новой.** Борда не видит ветки, и задача, по
|
|
30
38
|
которой работа лежит доделанной в локальной ветке, выглядит открытой у всех: колонку двигают
|
|
31
39
|
рукой, заявки нет, а ветка видна только на той машине, где её завели. Под один номер так
|
|
@@ -87,7 +95,7 @@ gh project item-add <номер борды> --owner <владелец> --url <а
|
|
|
87
95
|
который его показывает. Не нашлось ни того ни другого — задача не заводится, а строка документа
|
|
88
96
|
правится тем ходом, которым её прочитали.
|
|
89
97
|
|
|
90
|
-
Название
|
|
98
|
+
Название задачи говорит, что не так, а не что сделать: PR потом переводит его в сделанное.
|
|
91
99
|
Номер в заголовок руками не пишется — он известен только после создания, и команда дописывает
|
|
92
100
|
его сама.
|
|
93
101
|
|
|
@@ -97,7 +105,7 @@ gh project item-add <номер борды> --owner <владелец> --url <а
|
|
|
97
105
|
npm run check:board
|
|
98
106
|
```
|
|
99
107
|
|
|
100
|
-
Она смотрит только открытое:
|
|
108
|
+
Она смотрит только открытое: задачи на борде, номер и исполнителя у каждой открытой задачи,
|
|
101
109
|
а у каждого открытого PR — номер в заголовке, строку `Closes`, открытую задачу за ним и то,
|
|
102
110
|
что второго PR с тем же номером нет. Имя ветки не судит: у открытого PR его не переименовать.
|
|
103
111
|
|
|
@@ -209,6 +217,11 @@ Docs-skip: правка только в тестах хука, зеркала у
|
|
|
209
217
|
|
|
210
218
|
## Частые промахи
|
|
211
219
|
|
|
220
|
+
- **Сверка сразу после добавления отвечает «нет», когда карточка уже стоит.** Очередь работ отдаёт
|
|
221
|
+
новый элемент не в ту же секунду, в какую его завели, а последний шаг читает её следующим
|
|
222
|
+
вызовом. Ответ на это — перечитать очередь целиком, а не завести карточку второй раз: две записи
|
|
223
|
+
об одной задаче снимает только администратор. Сама команда заведения при этом требует правки:
|
|
224
|
+
состояние читается сразу за мутацией, без повтора, и ложный отказ здесь дороже задержки.
|
|
212
225
|
- `gh` в оболочке пользователя подменён — звать `/opt/homebrew/bin/gh` напрямую.
|
|
213
226
|
- Каталог добавлен целиком при чужом незакоммиченном рядом: чужая папка задачи уехала в главную ветку и стала отслеживаемой.
|
|
214
227
|
- `git add` с несколькими путями не добавляет ничего, если хоть один путь не существует:
|
|
@@ -223,7 +236,7 @@ Docs-skip: правка только в тестах хука, зеркала у
|
|
|
223
236
|
- `gh project` с `--owner` отвечает `unknown owner type`: владелец борды — другая учётная
|
|
224
237
|
запись, и правка идёт только через GraphQL.
|
|
225
238
|
- Заведённую задачу на борду сама она не забирает: репозиторий с ней не связан, и добавление
|
|
226
|
-
идёт отдельным вызовом.
|
|
239
|
+
идёт отдельным вызовом. Две задачи так и остались вне очереди работ — поэтому все четыре
|
|
227
240
|
шага и делает `npm run task:new`, а не рука.
|
|
228
241
|
- Исполнитель у задачи не проставляется сам ни при заведении через веб, ни при добавлении на
|
|
229
242
|
борду: из девяноста девяти открытых задач он стоял у двух.
|
|
@@ -25,6 +25,13 @@ description: Паттерн правила git-workflow. Брать на зав
|
|
|
25
25
|
|
|
26
26
|
Все четыре делает одна команда дерева, а не рука: делить их значит забывать последний.
|
|
27
27
|
|
|
28
|
+
**Команду, которой нет, паттерн не заменяет вызовами клиента.** Дерево, взявшее пакет впервые,
|
|
29
|
+
получает файлы проверок, но не записи о них в своём манифесте: раскладка правит ресурсы, а
|
|
30
|
+
манифест потребителя ей не принадлежит. Ходов отсюда два: завести команду тем же ходом либо
|
|
31
|
+
повторить все её шаги поимённо по перечню выше. Обход вызовами клиента выглядит исполнением до
|
|
32
|
+
последнего шага перечня: он забывается первым, потому что предыдущие уже дали видимый
|
|
33
|
+
результат.
|
|
34
|
+
|
|
28
35
|
```bash
|
|
29
36
|
npm run task:new -- --title 'Письма владельцу не уходят молча' \
|
|
30
37
|
--label bug --label area:api --slug mail-owner-silence < описание.md
|
|
@@ -156,6 +163,11 @@ Docs-skip: правка только в тестах хука, зеркала у
|
|
|
156
163
|
|
|
157
164
|
## Частые промахи
|
|
158
165
|
|
|
166
|
+
- **Сверка сразу после добавления отвечает «нет», когда карточка уже стоит.** Очередь работ отдаёт
|
|
167
|
+
новый элемент не в ту же секунду, в какую его завели, а последний шаг читает её следующим
|
|
168
|
+
вызовом. Ответ на это — перечитать очередь целиком, а не завести карточку второй раз: две записи
|
|
169
|
+
об одной задаче снимает только администратор. Сама команда заведения при этом требует правки:
|
|
170
|
+
состояние читается сразу за мутацией, без повтора, и ложный отказ здесь дороже задержки.
|
|
159
171
|
- Метка списка не поставлена при заведении: задача есть, а на доске её нет. Доска показывает
|
|
160
172
|
только то, чью метку знает.
|
|
161
173
|
- Перевод по списку не снял прежнюю метку: задача стоит в двух списках сразу.
|
|
@@ -40,6 +40,7 @@ git diff --name-only --diff-filter=U # что встало конфликт
|
|
|
40
40
|
| Что встало конфликтом | Как разрешается |
|
|
41
41
|
| -------------------------------- | ---------------------------------------------------------------------------------- |
|
|
42
42
|
| код | ловушка правила `git-workflow` про сторону-удаление; после — `npm run check:dupes` |
|
|
43
|
+
| сборка из описания | собирается заново из описания после того, как описание разрешено: строки в такой файл пишет генератор, и соединённые руками стороны дают файл, которого он не выдаст |
|
|
43
44
|
| спек в `docs/specs/` | сохранением обеих сторон, если обе дописывали; снятый одной стороной раздел остаётся снятым — правило `spec-driven`; после — `npm run check:specs` |
|
|
44
45
|
| компаньон правила рядом со скилом | сохранением обеих сторон — те же две дописи в одну таблицу; после — `npm run check:specs` |
|
|
45
46
|
| список работ (`docs/BACKLOG.md`) | признаком отбора — паттерн `doc-style-sweep` |
|
|
@@ -92,6 +93,13 @@ git checkout --theirs docs/BACKLOG.md && git add docs/BACKLOG.md
|
|
|
92
93
|
|
|
93
94
|
## Проверки после разрешения
|
|
94
95
|
|
|
96
|
+
**Конфликт в разложенном файле, который исполняется, разрешается тем же вызовом, каким
|
|
97
|
+
обнаружен.** Маркеры в теле гарда — синтаксическая ошибка, а не расхождение текста: ветка падает,
|
|
98
|
+
диспетчер отдаёт её код отказом, и следующего вызова оболочки уже не будет — вместе с ней
|
|
99
|
+
отбиваются и остальные двери, названные в объявлении этого гарда. Исполняемый файл узнаётся
|
|
100
|
+
строкой `# rt-hook:` в шапке; отложенное «поправлю потом» здесь означает заход, который нечем
|
|
101
|
+
продолжить.
|
|
102
|
+
|
|
95
103
|
Конфликт в текстах кода не задевает, и зелёная сборка про него ничего не говорит:
|
|
96
104
|
|
|
97
105
|
```bash
|
|
@@ -76,7 +76,7 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
|
|
|
76
76
|
Ведёт главный агент: субагент до владельца не достучится. Команда — `/grill-me`, один вопрос
|
|
77
77
|
за раз, к каждому — свой рекомендуемый ответ с доводом.
|
|
78
78
|
|
|
79
|
-
Шесть вопросов задаются
|
|
79
|
+
Шесть вопросов закрываются все, а задаются те, на которые разведка не ответила:
|
|
80
80
|
|
|
81
81
|
| Вопрос | Зачем |
|
|
82
82
|
| -------------------------------------------- | -------------------------------------------------------- |
|
|
@@ -33,13 +33,16 @@ description: Паттерн правила testing. Брать при правк
|
|
|
33
33
|
## Прогон
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
npx nx e2e
|
|
37
|
-
npx nx e2e
|
|
38
|
-
BASE_URL=http://localhost:{{dockerSitePort}} npx nx e2e site-e2e -- --project=chromium # против внешнего стенда
|
|
36
|
+
npx nx e2e <цель набора> -- --project=chromium
|
|
37
|
+
BASE_URL=http://localhost:$PROXY_SITE_PORT npx nx e2e <цель набора> -- --project=chromium # против внешнего стенда
|
|
39
38
|
```
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
Имена целей раннера и номера портов у каждого дерева свои: паттерн их не знает. Дерево называет
|
|
41
|
+
их своим профилем — переменными окружения либо разделом надстройки при этом паттерне, где стоят
|
|
42
|
+
готовые команды с его именами.
|
|
43
|
+
|
|
44
|
+
По умолчанию конфиг идёт на порт стенда сайта и подхватывает уже поднятый сервер. С `BASE_URL`
|
|
45
|
+
свой сервер не запускается.
|
|
43
46
|
|
|
44
47
|
Полный набор админки гоняется **одним воркером** (`--workers=1`): тесты с настоящей сессией
|
|
45
48
|
правят одни и те же объекты живой базы и в параллельном прогоне мешают друг другу. Одни и те
|
|
@@ -107,9 +110,9 @@ expect(answer.headers()['location']).toBe('/новый-адрес');
|
|
|
107
110
|
|
|
108
111
|
## Частые промахи
|
|
109
112
|
|
|
110
|
-
- **Порт
|
|
111
|
-
`ssr
|
|
112
|
-
сборку.
|
|
113
|
+
- **Порт сервера отрисовки занимать осторожно:** стенд разработчика ходит по тому же имени
|
|
114
|
+
`ssr:<порт отрисовки>` через `host-gateway`, и пока на нём висит чужой процесс, стенд отдаёт
|
|
115
|
+
чужую сборку.
|
|
113
116
|
- Браузер стоит один — chromium; узкий экран — `--project=mobile-chrome`. Ошибка «Executable
|
|
114
117
|
doesn't exist» разобрана в правиле `testing`: она же приходит после смены версии Playwright.
|
|
115
118
|
- Спеки админки без сессии пропускаются молча — прогон выглядит успешным, а проверено меньше
|
|
@@ -125,6 +128,13 @@ expect(answer.headers()['location']).toBe('/новый-адрес');
|
|
|
125
128
|
успевает его прочитать, и тест краснеет через раз. Проверяют либо конечное состояние
|
|
126
129
|
(`data-state` строки стал `done`), либо то же промежуточное — но на ответе, который тест сам
|
|
127
130
|
задержал и сам отпускает.
|
|
131
|
+
- **Двойник, перенесённый из спеки в общий файл набора, выходит из-под исключения проверки
|
|
132
|
+
повторов.** Она пропускает файлы спек и читает всё остальное, включая двойники и настройки, а
|
|
133
|
+
сверяет имя объявления — не значение и не назначение. Настройка, лежавшая в спеке под общим
|
|
134
|
+
именем, после переноса совпадает с одноимённой в другом слое, и проверка краснеет на файле,
|
|
135
|
+
которого правка не касалась: разбор такого красного занимает отдельный ход. Имя при переносе
|
|
136
|
+
получает приставку своего набора; строка в список известного не заводится — он только
|
|
137
|
+
сокращается.
|
|
128
138
|
- **Каталог сборки, удалённый под смонтированным томом, оставляет контейнер с пустым
|
|
129
139
|
корнем:** стенд отвечает 403 на всё, и падают сразу все тесты. Контейнер после
|
|
130
140
|
`rm -rf dist/apps/<приложение>` пересоздаётся.
|
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
тела задачи в дереве ещё верно.
|
|
15
15
|
|
|
16
16
|
- **Разрешение владельца, оставленное в репозитории, теряется на каждой новой ветке.** Оно
|
|
17
|
-
записано
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
разрешение живёт в репозитории, номер дописывается заново в каждую новую ветку.
|
|
17
|
+
записано в файл ветки, а следующая ветка отводится от главной и его не несёт: гард запрещает
|
|
18
|
+
разрешённую работу столько раз, сколько веток заведут до слияния. Отказ называет файл и молчит
|
|
19
|
+
о том, что запись принадлежит ветке. Пока разрешение живёт в репозитории, номер дописывается в
|
|
20
|
+
каждую новую ветку.
|
|
22
21
|
- **Имя чужого дерева в файлы репозитория не пишется, а путь к образцу — пишется.** Обе вещи
|
|
23
22
|
живут рядом с передачей захода именно поэтому: там законен полный путь, а в репозитории —
|
|
24
23
|
только ссылка без имени.
|
|
@@ -37,13 +36,11 @@
|
|
|
37
36
|
договорённость обязана его пережить: её сценарии получают номера в общей нумерации домена,
|
|
38
37
|
и на них ссылаются заголовки тестов. Обратное тоже верно — ход работы не кладётся в
|
|
39
38
|
`proposed/`: спек, в котором завелись шаги, снова становится планом и умирает после мержа.
|
|
40
|
-
- **У меню нет строки «вопрос не тот».** Меню годится там, где выбор
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
одного постановка была ложной. Там, где под сомнением сама уместность вопроса, его сперва
|
|
46
|
-
проверяют по репликам владельца — и чаще всего не задают.
|
|
39
|
+
- **У меню нет строки «вопрос не тот».** Меню годится там, где выбор закрыт; пока постановка
|
|
40
|
+
вопроса не подтверждена, владельцу нечем её отвергнуть — он выбирает из вариантов неверной
|
|
41
|
+
посылки. Если настройки требуют меню, к каждому вопросу добавляется свободный вариант. Три
|
|
42
|
+
вопроса ушли одним меню, у одного постановка была ложной: уместность вопроса сперва проверяют
|
|
43
|
+
по репликам владельца.
|
|
47
44
|
- **Субагент вопросов владельцу не задаёт.** Ни роли, ни конвейер до него не достучатся —
|
|
48
45
|
они возвращают текст главному агенту. Поэтому разбор ведёт главный агент, а роли стоят по
|
|
49
46
|
обе стороны от него.
|
|
@@ -91,11 +88,9 @@
|
|
|
91
88
|
соседа.
|
|
92
89
|
|
|
93
90
|
- **Копия образца папки задачи несёт шапку раскладки, и первая же правка отбивается гардом.**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
копирование руками — нет. Правится такая копия только записью заново: правку по месту гард
|
|
98
|
-
отбивает и её.
|
|
91
|
+
Копия под задачу выглядит разложенным файлом, и отказ называет адрес источника пакета — уводит
|
|
92
|
+
править образец вместо копии. Команда заведения задачи снимает шапку сама, копирование руками
|
|
93
|
+
— нет. Такая копия правится только записью заново.
|
|
99
94
|
- **Имя проекта в признаке готовности этапа спрашивается у сборщика, а не пишется по памяти.**
|
|
100
95
|
На неизвестное имя сборщик отвечает «задач не запущено» и выходит нулём: команда признака не
|
|
101
96
|
прогнала ни одной пробы и промолчала так же, как зелёный прогон. Видно это только по числу
|
|
@@ -122,19 +117,15 @@
|
|
|
122
117
|
профиль дерева, и лежит он вне дерева кода.
|
|
123
118
|
|
|
124
119
|
- **Тело задачи, написанное вперёд замысла, называет способ, и способ стареет раньше дефекта.**
|
|
125
|
-
|
|
126
|
-
уже
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
задача относится, а не с исполнения её тела. Расхождение уходит решением по ходу и меняет
|
|
130
|
-
способ, но не цель.
|
|
120
|
+
Задачу серии заводят за недели до взятия; к этому дню предложенный способ бывает уже неверен:
|
|
121
|
+
пакет уже умеет то, что задача звала написать, названного места в дереве нет. Работа поэтому
|
|
122
|
+
начинается с чтения файла, к которому задача относится, а не с исполнения её тела. Расхождение
|
|
123
|
+
меняет способ, но не цель.
|
|
131
124
|
|
|
132
125
|
- **Работа, упершаяся в разрешение, доводится до конца без той части, которую разрешение
|
|
133
|
-
открывает.**
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
пишется строками тела заявки — там его читает ревьювер; реплика владельцу живёт до следующего
|
|
137
|
-
сообщения и в приёмку не попадает.
|
|
126
|
+
открывает.** Прогон и разбор кончатся сами, а отбитое разрешение не кончится никогда: ход,
|
|
127
|
+
объявивший ожидание, останавливает работу целиком. Делается всё, что от разрешения не зависит;
|
|
128
|
+
непройденное пишется в тело заявки, где его читает ревьювер.
|
|
138
129
|
|
|
139
130
|
- **Слово владельца об устройстве — постановка, а не решение.** Названное им обычно уже живёт
|
|
140
131
|
в дереве под этим самым словом: у него есть имя на экране, раздел в спеке и поле в модели, и
|
|
@@ -144,17 +135,11 @@
|
|
|
144
135
|
спрашивается до правки.
|
|
145
136
|
|
|
146
137
|
- **Указание работать по ходу — это указание делать его шаги, включая меняющие историю.**
|
|
147
|
-
Отметка
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
ход её ни предписывал.
|
|
153
|
-
|
|
154
|
-
- **Строка ожидания живёт дольше причины, по которой её написали.** Записанная в ход работы,
|
|
155
|
-
она приходит в следующий заход раньше любой реплики и подтверждает себя сама: три указания
|
|
156
|
-
подряд не пересилили одну строку на диске. Снимается она тем же ходом, которым владелец
|
|
157
|
-
ответил, — а не тем, в котором о ней вспомнили.
|
|
138
|
+
Отметка этапа, отправка ветки и открытие заявки предписаны ходом, отдельного слова на каждый
|
|
139
|
+
не нужно. Общий запрет дерева на действие без просьбы, прочитанный буквально, даёт указание,
|
|
140
|
+
исполненное наполовину. Граница одна: прямое слово владельца о самом шаге — «ветку не
|
|
141
|
+
отправляй» действует, сколько бы раз ход её ни предписывал.
|
|
142
|
+
|
|
158
143
|
|
|
159
144
|
- **Очередь работ эпиком не кончается.** Занятый другими исполнителями или законченный эпик
|
|
160
145
|
означает следующую задачу из очереди, а не остановку: «свободных задач эпика нет» ответом на
|
|
@@ -165,6 +150,21 @@
|
|
|
165
150
|
колонку разбора и снятие её папки — обязательные шаги закрытия, и оба случаются тем же ходом,
|
|
166
151
|
которым открывается заявка. Ход, в котором больше ничего нет, работу не двигает, сколько бы
|
|
167
152
|
команд в нём ни стояло.
|
|
153
|
+
- **Черновик папки без номера теряется молча.** Он лежит вне истории, и его не видят ни борда,
|
|
154
|
+
ни сверка очереди, ни следующий заход. Порог брошенного разбора эту потерю не ловит: работа
|
|
155
|
+
проигрывает соседним поручениям в тот же час, а неделя проходит потом.
|
|
156
|
+
- **Стопка веток стоит дороже, и цена у неё названная.** Заявка в соседнюю ветку не запускает
|
|
157
|
+
конвейер, объявленный на базу главной; слияние базовой ветки закрывает заявку следующей как
|
|
158
|
+
слитую, хотя её правок в главной нет; конфликт от чужого слияния разрешается в каждой ветке
|
|
159
|
+
стопки заново. Расстановка, выбранная молча, собирает всю цену и не показывает ни одной её
|
|
160
|
+
части. Задачи, идущие одна из другой по коду, законно живут ветками от главной, пока правка
|
|
161
|
+
следующей не опирается на код предыдущей.
|
|
162
|
+
|
|
163
|
+
- **Находка посреди этапа ощущается частью текущей работы, когда предмет соседний.** Своего
|
|
164
|
+
признака у этого нет: до первой правки находки в дереве нет, а после неё файлы соседней работы
|
|
165
|
+
от файлов своей не отличаются. Поэтому сверяется перечень условий выхода замысла, а не ощущение.
|
|
166
|
+
Однажды такую правку остановил посторонний отказ по роду файла, а не сверка с замыслом: без него
|
|
167
|
+
она уехала бы в чужую ветку, и раздельного отката у двух работ не было бы.
|
|
168
168
|
|
|
169
169
|
## Поведение исполнителя — по разборам происшествий
|
|
170
170
|
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
перечисляет шесть обязательных вопросов таблицей, и пустая таблица проходит наравне с
|
|
208
208
|
заполненной.
|
|
209
209
|
- **Отказ гарда разговора исполняется задним числом.** Владелец видит незаданный вопрос вместе с
|
|
210
|
-
отбитым ходом: прозаический вопрос
|
|
210
|
+
отбитым ходом: прозаический вопрос — не вызов инструмента, и раньше поймать его нечем. Гард
|
|
211
211
|
отмечает пропуск, но не отменяет его.
|
|
212
212
|
- **Обход требования папки нужен там, где работа вливается частями.** Тогда её до конца не
|
|
213
213
|
разбирают, а причина остаётся в заявке.
|