@rt-tools/agent-kit 0.18.0 → 0.20.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/check-board.github.mjs +2 -2
- package/assets/checks/check-states.mjs +1 -1
- package/assets/defaults/gate-map.sh +6 -1
- package/assets/defaults/shell.sh +8 -0
- package/assets/hooks/postmortem-guard.sh +12 -3
- package/assets/hooks/turn-exit-guard.sh +5 -5
- package/assets/laws/verifiability.md +5 -0
- package/assets/patterns/browser-verification-measure.md +46 -0
- package/assets/patterns/git-workflow-commit.github.md +14 -0
- package/assets/patterns/git-workflow-merge.md +17 -0
- package/assets/patterns/task-flow-archive.md +27 -0
- package/assets/patterns/task-flow-handoff.md +11 -1
- package/assets/patterns/task-flow-resume.md +5 -0
- package/assets/pitfalls/git-workflow.github.md +6 -1
- package/assets/pitfalls/spec-driven.md +8 -0
- package/assets/pitfalls/task-flow.md +13 -0
- package/assets/pitfalls/testing.md +9 -0
- package/assets/pitfalls/turn-conduct.md +8 -0
- package/assets/skills/agent-kit.md +5 -1
- package/assets/templates/findings.md +27 -0
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +3 -0
- package/bin/agent-kit.js.map +1 -1
- package/lib/commands.d.ts +5 -0
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +58 -0
- package/lib/commands.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.20.0.tgz +0 -0
- package/rt-tools-agent-kit-0.18.0.tgz +0 -0
|
@@ -241,7 +241,7 @@ function checkEvicted(pull, options) {
|
|
|
241
241
|
* своей задачи; сверка же смотрит на состояние очереди целиком.
|
|
242
242
|
*
|
|
243
243
|
* Четыре PR так и простояли черновиками двое суток — разбор
|
|
244
|
-
*
|
|
244
|
+
* запись «2026-08-18-ready-work-left-in-drafts» в приёме.
|
|
245
245
|
*/
|
|
246
246
|
function checkReadyDraft(pull, options) {
|
|
247
247
|
if (pull.isDraft !== true) {
|
|
@@ -266,7 +266,7 @@ function checkReadyDraft(pull, options) {
|
|
|
266
266
|
*
|
|
267
267
|
* Судится только прямое «конфликтует»: `UNKNOWN` означает, что хостинг сливаемость ещё считает,
|
|
268
268
|
* и строка о нём краснела бы на каждой свежей вершине. Две заявки так и ушли в разбор с
|
|
269
|
-
* конфликтом — разбор
|
|
269
|
+
* конфликтом — разбор запись «2026-08-20-drafts-cleared-without-re-reading-pr-state» в приёме.
|
|
270
270
|
*/
|
|
271
271
|
function checkConflicting(pull) {
|
|
272
272
|
if (pull.mergeable !== 'CONFLICTING') {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* паттерн до последнего раздела, следующего движения в нём нет, и ход кончается
|
|
7
7
|
* отчётом. Так простояло состояние «замысел записан» — оно встречалось один раз,
|
|
8
8
|
* клеткой таблицы, и дыру нашло происшествие, а не проверка. Разбор —
|
|
9
|
-
*
|
|
9
|
+
* запись «2026-08-21-turn-ended-at-the-written-plan» в приёме.
|
|
10
10
|
*
|
|
11
11
|
* Сверяются два множества в обе стороны:
|
|
12
12
|
* перечень — таблица состояний в правиле ведения работы: имя и ведущий паттерн;
|
|
@@ -121,8 +121,13 @@ skill_for_default() {
|
|
|
121
121
|
# скриптов зависимостью не является, и правило про версии на неё не вступает.
|
|
122
122
|
# Оговорка: удаление зависимости приходит правкой без номера версии и сюда не
|
|
123
123
|
# попадает — его ловит снимок дерева, который правится тем же коммитом.
|
|
124
|
+
# Своя редакция зависимостью не является: строка `"version"` в собственном
|
|
125
|
+
# манифесте говорит о выпуске этого пакета, а не о чужой версии, которую он
|
|
126
|
+
# тянет. Признак номера её ловил наравне с зависимостью, и подъём своей версии
|
|
127
|
+
# вёл исполнителя в правило о чужих версиях — не туда, где сказано, как выпускают.
|
|
124
128
|
*/package.json)
|
|
125
|
-
printf '%s' "$written" | grep -
|
|
129
|
+
printf '%s' "$written" | grep -v '"version"[[:space:]]*:' \
|
|
130
|
+
| grep -qE '"(dependencies|devDependencies|peerDependencies|optionalDependencies|overrides|resolutions|packageManager)"|"[^"]+"[[:space:]]*:[[:space:]]*"[~^]?[0-9]+\.[0-9]+' \
|
|
126
131
|
&& printf '%s\n' 'dependencies' ;;
|
|
127
132
|
*/pnpm-lock.yaml | */pnpm-workspace.yaml | */package-lock.json) printf '%s\n' 'dependencies' ;;
|
|
128
133
|
|
package/assets/defaults/shell.sh
CHANGED
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
# интерпретатора, будет отбита наравне с командой правки. Узкий список стоил бы дороже —
|
|
18
18
|
# пропущенная форма записи возвращает обход целиком, а найти её можно только промахом.
|
|
19
19
|
#
|
|
20
|
+
# Удаление и перенос стоят в списке нарочно, а не по недосмотру. Снятие файла — правка
|
|
21
|
+
# разрушительнее любой записи: записанное видно в дереве и откатывается, а снятое без замысла не
|
|
22
|
+
# оставляет следа вовсе, и восстанавливать его приходится из истории. Цена этого выбора известна
|
|
23
|
+
# и платится не там, где её ждут: своё временное, положенное под корнем кода, снимается командой,
|
|
24
|
+
# и гард судит это правкой приложения — требует замысла на диске за действие, к приложению не
|
|
25
|
+
# относящееся. Отличить одно от другого признак не может: путь у обоих лежит под тем же корнем.
|
|
26
|
+
# Лечится это местом, а не признаком, — и сказано об этом ловушкой правила ведения работы.
|
|
27
|
+
#
|
|
20
28
|
# Перенаправление в пустое устройство и в поток ошибок снимается до разбора: файла оно не
|
|
21
29
|
# пишет, а выглядит как перенаправление в файл. Так глушат вывод команды чтения, и без этого
|
|
22
30
|
# `grep -rn x libs/ 2>/dev/null` судится наравне с записью — правило требуется на чтение, а
|
|
@@ -40,9 +40,18 @@ transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/nu
|
|
|
40
40
|
|
|
41
41
|
root="${CLAUDE_PROJECT_DIR:-.}"
|
|
42
42
|
|
|
43
|
-
# Каталог записей у дерева
|
|
44
|
-
#
|
|
45
|
-
|
|
43
|
+
# Каталог записей у дерева свой, и называет его настройка дерева — тем же ключом, каким его
|
|
44
|
+
# читает отправка груза. Одно имя на обе стороны: дерево, унёсшее каталог из истории, иначе
|
|
45
|
+
# получало бы гард, ищущий записи по прежнему адресу, — и тот молчал бы всегда. Переменная
|
|
46
|
+
# остаётся обходом на один запуск, а пустая строка в любой из двух — отказ дерева от требования:
|
|
47
|
+
# дереву, которое записей не ведёт, гард не навязывается.
|
|
48
|
+
if [ -n "${RT_POSTMORTEMS_DIR+set}" ]; then
|
|
49
|
+
notes_dir="$RT_POSTMORTEMS_DIR"
|
|
50
|
+
elif [ -f "$root/.claude/rt-kit.json" ]; then
|
|
51
|
+
notes_dir="$(jq -r '.postmortems // "docs/postmortems"' "$root/.claude/rt-kit.json" 2>/dev/null)"
|
|
52
|
+
else
|
|
53
|
+
notes_dir="docs/postmortems"
|
|
54
|
+
fi
|
|
46
55
|
[ -z "$notes_dir" ] && exit 0
|
|
47
56
|
[ -d "$root/$notes_dir" ] || exit 0
|
|
48
57
|
|
|
@@ -166,7 +166,7 @@ work_re='git (add|commit|push|checkout|merge|rm)|npm run|pnpm (run|exec)|nx (bui
|
|
|
166
166
|
# подтягивание, просмотр истории, чтение заявок и прогонов. Образец работы называет их работой,
|
|
167
167
|
# потому что знает только первое слово — `git` и `gh` стоят в нём целиком, — и ход, в котором
|
|
168
168
|
# исполнитель перешёл на главную ветку, прочитал историю и написал владельцу отчёт, выходил
|
|
169
|
-
# отсюда нулём. Разбор —
|
|
169
|
+
# отсюда нулём. Разбор — запись «2026-08-25-read-only-turn-counted-as-work» в приёме.
|
|
170
170
|
#
|
|
171
171
|
# Разведка выглядит работой лучше всего остального: в ней команды, числа и точные ответы. Тем
|
|
172
172
|
# она и опасна — ход, набитый ею, читается как полный и владельцем, и самим заходом.
|
|
@@ -179,7 +179,7 @@ part_re='&&|\|\||;|\n'
|
|
|
179
179
|
# Ожидание чужого шага. Прогон, разбор владельцем и слияние идут без исполнителя и от взгляда
|
|
180
180
|
# быстрее не становятся — правило прямо говорит, что состоянием работы это не бывает. Судится
|
|
181
181
|
# только ПОСЛЕДНЕЕ действие хода: ожидание в середине законно, а запуск работы в фоне работой
|
|
182
|
-
# остаётся. Разбор —
|
|
182
|
+
# остаётся. Разбор — запись «2026-08-25-turn-ended-on-waiting» в приёме.
|
|
183
183
|
#
|
|
184
184
|
# Прежний признак спрашивал одно: была ли за ход работа. Ход, где разобран конфликт, сделаны
|
|
185
185
|
# коммит и пуш, а последним действием стал цикл до готовности прогона, проходил его целиком —
|
|
@@ -264,7 +264,7 @@ commands="$(printf '%s' "$verdict" | jq -r '.ran // ""' 2>/dev/null)"
|
|
|
264
264
|
# Ровно так ход и вставал: задача взята, номер назван владельцу, отчёт написан — и следующее
|
|
265
265
|
# действие состояния «задача-взята», написать замысел, не сделано. Отчёт выглядит работой лучше
|
|
266
266
|
# всякой другой, а страж, знающий только «была ли за ход работа», подтверждает это: работа была.
|
|
267
|
-
# Разбор —
|
|
267
|
+
# Разбор — запись «2026-08-25-task-taken-and-turn-ended» в приёме.
|
|
268
268
|
#
|
|
269
269
|
# Папка, разобранная коммитом ветки, сюда не попадает: `archived` означает отданную работу, и её
|
|
270
270
|
# судит прежний ярус. Ветка без номера задачи не судится вовсе — под пробу заводят и такие.
|
|
@@ -332,7 +332,7 @@ fi
|
|
|
332
332
|
# вся она по сданной задаче: отдача завершает прошлую работу, а не ход. Девять разборов
|
|
333
333
|
# происшествий за сутки описывают девять разных остановок, и во всех девяти последним действием
|
|
334
334
|
# хода был текст владельцу: отчёт, сводка, объявление намерения.
|
|
335
|
-
# Разбор —
|
|
335
|
+
# Разбор — запись «2026-08-25-handover-turn-ends-on-intent» в приёме.
|
|
336
336
|
if [ "$handed_over" = "true" ] && [ "$started_next" != "true" ]; then
|
|
337
337
|
reason="BLOCKED by turn-exit-guard: заявка открыта, а по следующей работе за этот ход не сделано ничего.
|
|
338
338
|
|
|
@@ -385,7 +385,7 @@ fi
|
|
|
385
385
|
# Работа, оставшаяся в рабочем дереве. Ветка ушла вперёд своей удалённой ссылки, а заявки при
|
|
386
386
|
# ней в этом ходе не открывали: сделанное лежит там, где его не видит никто, кроме сделавшего.
|
|
387
387
|
# Признак читается без сети и молчит там, где ссылки нет вовсе — под пробу заводят и такие ветки.
|
|
388
|
-
# Разбор —
|
|
388
|
+
# Разбор — запись «2026-08-25-fifteen-branches-over-one-index» в приёме.
|
|
389
389
|
if [ "$worked" = "true" ] && [ "$handed_over" != "true" ]; then
|
|
390
390
|
unpushed="$(git -C "$root" rev-list --count '@{u}..HEAD' 2>/dev/null)"
|
|
391
391
|
if [ -n "$unpushed" ] && [ "$unpushed" -gt 0 ] 2>/dev/null; then
|
|
@@ -109,3 +109,8 @@
|
|
|
109
109
|
судит место, выведенное из-под проверки, — здесь выведено не место, а вся она, и следа в коде
|
|
110
110
|
не остаётся никакого. Расхождение закрывается тем, на что проверка указала, а несогласие с ней
|
|
111
111
|
самой — вопрос к владельцу.
|
|
112
|
+
- **Правка вида проверяется на каждом пороге раскладки, а не на одной ширине.** Пороги — это
|
|
113
|
+
места, где раскладка меняется, и промах живёт ровно там: по обе стороны от порога она
|
|
114
|
+
собирается по-разному, а посередине выглядит верной. Проверенная на двух крайних ширинах
|
|
115
|
+
правка отвечает только про эти две, и всё, что между ними, не видел никто. Пары вокруг порога
|
|
116
|
+
проверяются обе: одна ширина говорит лишь про ту сторону, на которую попала.
|
|
@@ -48,6 +48,52 @@ description: Паттерн правила browser-verification. Брать, к
|
|
|
48
48
|
главной сайта. Счёт годится любому наследуемому свойству: смотрится не одно значение, а число
|
|
49
49
|
узлов с неожиданным.
|
|
50
50
|
|
|
51
|
+
## Замер по всем порогам разом
|
|
52
|
+
|
|
53
|
+
Замер по одной ширине за вызов даёт числа разных минут: между вызовами страница
|
|
54
|
+
перерисовывается, и сравнивать их нельзя. Ширины поэтому гоняются пачкой в одном заходе —
|
|
55
|
+
каждая живёт своим кадром, замер снимается со всех сразу:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
await (async (address, widths, row) => {
|
|
59
|
+
const frames = widths.map((width) => {
|
|
60
|
+
const frame = document.createElement('iframe');
|
|
61
|
+
frame.style.cssText = `width:${width}px;height:900px;border:0;position:fixed;left:-9999px`;
|
|
62
|
+
frame.src = address;
|
|
63
|
+
document.body.appendChild(frame);
|
|
64
|
+
return { width, frame };
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await Promise.all(frames.map(({ frame }) => new Promise((done) => (frame.onload = done))));
|
|
68
|
+
|
|
69
|
+
return frames.map(({ width, frame }) => {
|
|
70
|
+
const view = frame.contentWindow;
|
|
71
|
+
const doc = frame.contentDocument;
|
|
72
|
+
const cells = [...doc.querySelectorAll(row)];
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
asked: width,
|
|
76
|
+
got: view.innerWidth,
|
|
77
|
+
heights: [...new Set(cells.map((el) => Math.round(el.getBoundingClientRect().height)))],
|
|
78
|
+
scrolls: doc.documentElement.scrollWidth > doc.documentElement.clientWidth,
|
|
79
|
+
escaped: cells.filter((el) => el.getBoundingClientRect().left > view.innerWidth).length,
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
})('/screen', [360, 599, 600, 904, 905, 1239, 1240, 1440], '.field');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Ответ читается по трём признакам, и первый не про вид:
|
|
86
|
+
|
|
87
|
+
- **высоты соседей одной строки равны между собой** — набор значений в `heights` длиной больше
|
|
88
|
+
единицы означает, что поля встали разного размера;
|
|
89
|
+
- **поперечной прокрутки нет** — `scrolls` истинно там, где содержимое шире кадра;
|
|
90
|
+
- **ни одна левая граница не выходит за ширину кадра** — `escaped` больше нуля. На снимке этого
|
|
91
|
+
не видно вовсе: элемент за правым краем выглядит отсутствующим.
|
|
92
|
+
|
|
93
|
+
Ширина кадра меньше заказанной на полосу прокрутки, поэтому сравнивают с `got`, а не с числом
|
|
94
|
+
из списка: порог, названный по заказанной ширине, на кадре оказывается по другую сторону от
|
|
95
|
+
себя.
|
|
96
|
+
|
|
51
97
|
## Узкий экран
|
|
52
98
|
|
|
53
99
|
`resize_window` не работает, когда Chrome в полноэкранном режиме: инструмент рапортует успех,
|
|
@@ -26,6 +26,20 @@ description: Паттерн правила git-workflow. Брать на зав
|
|
|
26
26
|
|
|
27
27
|
Все четыре шага делает одна команда дерева, а не рука: делить их значит забывать третий.
|
|
28
28
|
|
|
29
|
+
**Локальные ветки этой задачи читаются до заведения новой.** Борда не видит ветки, и задача, по
|
|
30
|
+
которой работа лежит доделанной в локальной ветке, выглядит открытой у всех: колонку двигают
|
|
31
|
+
рукой, заявки нет, а ветка видна только на той машине, где её завели. Под один номер так
|
|
32
|
+
завелась вторая ветка со своей папкой задачи и своим замыслом — то есть работа была спланирована
|
|
33
|
+
второй раз, и выбирать из двух пришлось владельцу.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
git branch --list '<КЛЮЧ>-<номер>-*'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Одна строка ответа означает, что работа уже начата: её состояние читается в ходе работы её
|
|
40
|
+
папки, а не заводится заново. Пустой ответ говорит только про эту машину — ветка, заведённая на
|
|
41
|
+
другой и не отданная хостингу, не видна и отсюда.
|
|
42
|
+
|
|
29
43
|
**Очередь работ спрашивается до заведения задачи, а не после.** Найденное собственной сверкой
|
|
30
44
|
ощущается новым, и это ощущение — единственное, что стоит за решением завести задачу: команда
|
|
31
45
|
заведения отвечает за свои вызовы и о содержании очереди не знает ничего. Спрашивается она
|
|
@@ -133,6 +133,23 @@ PR описывал дерево на день, когда его написал
|
|
|
133
133
|
что ветка везёт теперь, и прогон идёт заново: зелёные задания прошлого прогона после вливания не
|
|
134
134
|
значат ничего.
|
|
135
135
|
|
|
136
|
+
## Чужие папки задач приезжают вместе с главной веткой
|
|
137
|
+
|
|
138
|
+
Мерж главной ветки везёт всё, что в неё влилось, — включая папки задач соседних работ, если те
|
|
139
|
+
уехали в главную неразобранными. В своей ветке они выглядят как своё: лежат в том же каталоге,
|
|
140
|
+
названы тем же порядком, и разбирать их отсюда некому.
|
|
141
|
+
|
|
142
|
+
Кнопку слияния при этом нажимает человек, а там, где он это делает, хуков нет: гард, стерегущий
|
|
143
|
+
разбор папки, до этого пути не достаёт. Поэтому сверка очереди работ гоняется сразу после мержа
|
|
144
|
+
главной, а не перед пушем:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run check:board
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Она называет папку, у которой нет открытой задачи, — это и есть приехавшая чужая. Своей рукой
|
|
151
|
+
она не разбирается: снимает её тот, чья это работа, и делает это в своей ветке.
|
|
152
|
+
|
|
136
153
|
## Частые промахи
|
|
137
154
|
|
|
138
155
|
- «Сохранить обе стороны» применено ко всем файлам одинаково: в спеке это верно, в коде и в
|
|
@@ -20,6 +20,16 @@ description: Паттерн правила task-flow. Брать, когда т
|
|
|
20
20
|
|
|
21
21
|
## Состояние `разбор-кончился`: папка задачи разбирается
|
|
22
22
|
|
|
23
|
+
Разбор здесь свой, а не чужой: имя состояния говорит о папке задачи, которую разбирают
|
|
24
|
+
следующим шагом, — не о заявке, которую читает ревьювер, и не о просьбе владельца, с разбора
|
|
25
|
+
которой работа начиналась. Слово одно на три дела, и на беглом чтении имя выглядит чужим шагом:
|
|
26
|
+
исполнитель говорил владельцу, что ждёт разбора, и брался за следующую задачу, а готовая работа
|
|
27
|
+
стояла лишний ход и возвращалась в работу рукой владельца.
|
|
28
|
+
|
|
29
|
+
Ждать при этом состоянии нечего. Вход в него — два признака, оба читаются в дереве: набор
|
|
30
|
+
зелёный и тексты приведены. Одобрение владельца входом не является, и работа, ждущая его при
|
|
31
|
+
сошедшихся признаках, стоит зря.
|
|
32
|
+
|
|
23
33
|
Разбор идёт по трём исходам, а не по двум.
|
|
24
34
|
|
|
25
35
|
**Первым отбирается действующее требование.** Всё, что останется верным и завтра, становится
|
|
@@ -161,6 +171,14 @@ npm run cargo:mark -- --state fixed \
|
|
|
161
171
|
замеченная не разбором, а по ходу работы. Работа вне эпика показывает находки владельцу тем же
|
|
162
172
|
ходом.
|
|
163
173
|
|
|
174
|
+
**Имя файла находок собирается из имени замысла, а не выдумывается заходом.** Файл — это
|
|
175
|
+
`<имя замысла>-findings.md` рядом с самим замыслом: замысел `<тема>.md` копит находки в
|
|
176
|
+
`<тема>-findings.md`. Имя, выбранное на месте, читается только тем заходом, который его дал:
|
|
177
|
+
следующий ищет находки этого эпика перебором каталога замыслов и, не найдя, заводит второй
|
|
178
|
+
файл о том же — а владелец читает один из двух. Постоянного места здесь мало: у каждого эпика
|
|
179
|
+
свой файл, и находит его по имени тот, кто пришёл к замыслу, а не к каталогу. Форма файла —
|
|
180
|
+
образец находок среди образцов пакета.
|
|
181
|
+
|
|
164
182
|
**Находки, вернувшиеся после того, как ветка ушла, едут веткой следующей задачи.** Пуш в снятую
|
|
165
183
|
ветку её не обновляет, а заводит заново: коммит остаётся вне главной ветки и пропадает вместе
|
|
166
184
|
с ней. Следующая задача к этому времени уже взята — её веткой уборка за предыдущей и едет.
|
|
@@ -172,6 +190,15 @@ npm run cargo:mark -- --state fixed \
|
|
|
172
190
|
деление идёт задним числом, вместе с правкой ссылок на файл. Не влезает — заводится следующая
|
|
173
191
|
часть, и раздел пишется сразу в неё.
|
|
174
192
|
|
|
193
|
+
**Часть называется задачей, которая её завела, а не своим порядковым номером.** Имя —
|
|
194
|
+
`<имя замысла>-findings-<КЛЮЧ>-<номер>.md`. Один эпик ведут несколько рабочих деревьев разом, и
|
|
195
|
+
«следующая часть» каждое из них видит своей: две ветки заводят файл с одним именем, а
|
|
196
|
+
столкновение обнаруживается только при вливании главной ветки — конфликтом на весь файл, где обе
|
|
197
|
+
стороны верны и сложением не разрешаются. Номер задачи занят ею одной, и достаться двум деревьям
|
|
198
|
+
он не может. Первая часть номера не несёт и задним числом не переименовывается: переименование
|
|
199
|
+
правит ссылки во всех текстах, которые на неё смотрят, ради ровного ряда имён. Порядок между
|
|
200
|
+
частями не нужен — находки друг друга не продолжают, и владелец читает их разом.
|
|
201
|
+
|
|
175
202
|
**Наружу без слова владельца уезжает только сводка наблюдений.** Она говорит, чем пользовались
|
|
176
203
|
и чем не пользовались ни разу, — это факт, и мнением он не станет. Предложение — другое дело:
|
|
177
204
|
это заготовка правки чужого дерева, и часть заготовок отпадает при первом же чтении. Уехавшая
|
|
@@ -100,6 +100,8 @@ mkdir -p <каталог передачи>
|
|
|
100
100
|
|
|
101
101
|
Что учесть в этом заходе:
|
|
102
102
|
|
|
103
|
+
- разбор работы правилами по <КЛЮЧ>-<номер> запущен фоном и не вернулся — находки писать в
|
|
104
|
+
`<имя замысла>-findings.md` рядом с замыслом эпика;
|
|
103
105
|
- стенды уже подняты владельцем, свой не поднимать;
|
|
104
106
|
- зависимости этого дерева отстают от главной ветки — при падении сборки на чужой ошибке
|
|
105
107
|
сперва установка зависимостей;
|
|
@@ -137,7 +139,15 @@ mkdir -p <каталог передачи>
|
|
|
137
139
|
4. **Сделано и следующий шаг** — одной строкой каждое; подробности уже в ходе работы.
|
|
138
140
|
5. **Что учесть** — особенности этого захода, которых нет ни в правилах, ни в ходе работы:
|
|
139
141
|
поднятые стенды, отставшие зависимости, чужие процессы на портах, незакрытые вопросы к
|
|
140
|
-
|
|
142
|
+
владельцу, запущенный фоном и не вернувшийся разбор.
|
|
143
|
+
|
|
144
|
+
**Разбор, запущенный фоном и не вернувшийся к концу захода, называется строкой в «Что учесть».**
|
|
145
|
+
Отвечает роль в переписку, а переписки к следующему заходу уже нет: ответ, пришедший после
|
|
146
|
+
закрытия, не читает никто, и находки пропадают целиком вместе с тем, ради чего разбор и
|
|
147
|
+
запускали. На диске следа тоже нет — файл находок пишет исполнитель по ответу, а ответа ещё не
|
|
148
|
+
было. Строка называет задачу, по которой разбор идёт, и файл, куда писать вернувшееся: без
|
|
149
|
+
второго следующий заход знает, что чего-то ждёт, и не знает, куда это класть. Своего раздела
|
|
150
|
+
разбору не заводится — в заходе, где его не запускали, раздел стоял бы пустым.
|
|
141
151
|
|
|
142
152
|
### Путь владельцу
|
|
143
153
|
|
|
@@ -188,3 +188,8 @@ git log --oneline origin/main..HEAD
|
|
|
188
188
|
слово стоит на месте: «семь» простояло над восемью перечисленными до самого итога и поехало бы
|
|
189
189
|
дальше — в отчёт и в замысел эпика. Пишется либо перечень без числа, либо число, посчитанное
|
|
190
190
|
тем же ходом, каким пишется итог.
|
|
191
|
+
- **Красный набор на ветке, не тронувшей ни строки кода, спрашивается у соседних заходов раньше,
|
|
192
|
+
чем у своей правки.** Стенд у прогонов один на машину: соседний заход, поднявший его под себя,
|
|
193
|
+
роняет чужой набор, и падение выглядит поломкой среды. Прочитанное так, оно заводит второй
|
|
194
|
+
заход на то же место — чинить то, что не ломалось. Порядок обратный: сперва читаются соседние
|
|
195
|
+
заходы и занятые порты, и только потом своя правка.
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
же, чего гард и добивается.
|
|
194
194
|
- **Свои черновики судятся все разом.** Уход в соседнюю ветку выключал гард целиком: за один
|
|
195
195
|
заход так разошлись с главной четыре заявки подряд, и заметил это владелец, а не проверка.
|
|
196
|
-
Разбор —
|
|
196
|
+
Разбор — запись «2026-08-25-run-left-unwatched» в приёме.
|
|
197
197
|
- **Подпись машинной записи на каждом коммите вклада.** Пять коммитов одной стопки уехали
|
|
198
198
|
подписанными владельцем, который правки не делал: гард судит только коммит, назвавшийся
|
|
199
199
|
машинной записью, и ищет расхождение в числе служебного адреса.
|
|
@@ -219,3 +219,8 @@
|
|
|
219
219
|
ни статус, ни сверка, а команда, прошедшая между прятаньем и возвратом, пишет в те же файлы —
|
|
220
220
|
и возврат встаёт конфликтом. Так ушли в прятанье восемь незакоммиченных файлов при живом
|
|
221
221
|
запрете на эту команду: запрет читался в начале захода, а команда набиралась через сорок ходов.
|
|
222
|
+
- **Очередь конвейера, заведённая на всё дерево, снимает ждущего чужим пушем.** Группа
|
|
223
|
+
одновременности с отменой уже идущего экономит машину ровно до первого соседа: его пуш снимает
|
|
224
|
+
прогон чужой ветки, и та остаётся с вершиной без единого прогона — заявка при этом выглядит
|
|
225
|
+
непроверенной, а прогонять её заново некому. Группа поэтому заводится своя на ветку, и общей
|
|
226
|
+
остаётся только у шагов, которым нужен стенд: их и правда нельзя гнать вдвоём на одной машине.
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
его привязка перестают находиться друг по другу. После разрешения гоняется
|
|
35
35
|
`npm run check:specs` — конфликт в спеке кода не задевает, и ни сборка, ни линтеры его не
|
|
36
36
|
увидят.
|
|
37
|
+
- **Сложение отвечает на две дописи, а не на снятие: сторона, у которой текста нет вовсе, тоже
|
|
38
|
+
правка.** Раздел, вынесенный в описание прошлого или свёрнутый в правило, сложением
|
|
39
|
+
возвращается обратно — один абзац встаёт в двух редакциях, и снятая читается как
|
|
40
|
+
действующая. Случай не редкий: он приходит ровно тогда, когда снятия потребовал сам слой
|
|
41
|
+
правил, а ветки, начатые раньше, несут прежнюю редакцию. Признак прямой — у одной стороны
|
|
42
|
+
текста нет; тогда конфликт решается тем, что с разделом сделали, а не сложением. Снятое
|
|
43
|
+
остаётся снятым, а допись второй стороны переезжает туда, куда уехал раздел, — или не
|
|
44
|
+
переезжает вовсе, если уехал он потому, что стал правилом.
|
|
37
45
|
|
|
38
46
|
- **Строку требования к соседнему ресурсу не проверяет ничто, и расхождение видно только
|
|
39
47
|
счётом.** Правило без неё выглядит целым: разделы на месте, привязки сходятся, сверка
|
|
@@ -81,6 +81,14 @@
|
|
|
81
81
|
задание, он даёт заходу работу, которой владелец не просил. То же с любой репликой без
|
|
82
82
|
глагола: спросить, что с этим делать, дешевле, чем написать полсотни файлов мимо просьбы.
|
|
83
83
|
|
|
84
|
+
- **Своё временное кладётся вне дерева кода — иначе его снятие судится как правка приложения.**
|
|
85
|
+
Признак записи, которым гарды судят команду оболочки, считает записью и удаление, и это в нём
|
|
86
|
+
нарочно: снятое без замысла не оставляет следа вовсе. Отличить свой временный каталог от
|
|
87
|
+
каталога домена признаку нечем — путь у обоих под тем же корнем, — поэтому гард требует
|
|
88
|
+
замысла на диске за уборку черновика, к приложению не относящуюся. Каталог для своего
|
|
89
|
+
временного называет профиль дерева, и лежит он вне дерева кода; положенный внутрь, он платит
|
|
90
|
+
этим отказом при каждой уборке.
|
|
91
|
+
|
|
84
92
|
- **Тело задачи, написанное вперёд замысла, называет способ, и способ стареет раньше дефекта.**
|
|
85
93
|
Задача серии заводится за недели до того, как её берут, и к этому дню предложенный ход бывает
|
|
86
94
|
уже неверен: привезённое пакетом умеет то, что задача звала написать, названного места в
|
|
@@ -201,3 +209,8 @@
|
|
|
201
209
|
— сперва на отказе конца хода, потом на переводе колонки, и оба раза номер дописывался заново.
|
|
202
210
|
Место такому разрешению там же, где передача захода: оно не откатывается вместе с правкой и не
|
|
203
211
|
принадлежит ни одной задаче.
|
|
212
|
+
- **Задача, вынесенная в другой эпик, снимается из состава прежнего тем же ходом.** Вынос — два
|
|
213
|
+
движения, и сделанное наполовину оставляет задачу в двух составах сразу: итог прежнего эпика
|
|
214
|
+
считается по числу, которого в нём уже нет, и эпик выглядит незакрытым при всех сделанных
|
|
215
|
+
работах. Итог вписывается там же, где правится состав: отложенный, он пишется по памяти о том,
|
|
216
|
+
сколько задач было, а не о том, сколько осталось.
|
|
@@ -38,6 +38,15 @@
|
|
|
38
38
|
- **Первому прогону сразу после установки браузера верить нельзя.** Два падения сквозного
|
|
39
39
|
набора не повторились ни при отдельном прогоне тех же тестов, ни при втором полном. Такой
|
|
40
40
|
прогон повторяют, а выводы делают по второму.
|
|
41
|
+
- **Повторный прогон через гейт пуша повторяет весь набор, а не упавший тест.** Гейт гоняет то,
|
|
42
|
+
что перечислил профиль дерева, целиком и с нуля: у сквозного набора это минуты, и каждая
|
|
43
|
+
попытка пуша стоит их заново. Соседняя ловушка верна ровно до этого места: повторить дёшево —
|
|
44
|
+
через гейт уже нет, и «повторить» превращается в «пушить, пока не пройдёт». Полный набор
|
|
45
|
+
поэтому гоняется руками до вызова пуша, а гейт только подтверждает уже известное. Тест,
|
|
46
|
+
упавший в полном наборе и прошедший при отдельном прогоне, зелёным не считается: это
|
|
47
|
+
нестабильный тест, и он заводится задачей тем же ходом. Прогон до зелёного уносит признак
|
|
48
|
+
вместе с падением, и следующий заход встречает то же самое как новость — а отличить чужую
|
|
49
|
+
нестабильность от своей регрессии ему нечем: оба случая выглядят одинаково.
|
|
41
50
|
- Сквозная спека, которой нужен вход, без учётных данных в окружении пропускается молча — в
|
|
42
51
|
отчёте она значится `skipped`, и прогон выглядит успешным. Имена переменных — при дереве.
|
|
43
52
|
- **Справочник флоу вторых сценариев не заводит.** В `docs/E2E_<ДОМЕН>_FLOWS.md` кладут то,
|
|
@@ -80,3 +80,11 @@
|
|
|
80
80
|
в него, встаёт целиком там, где мимо него шло ещё несколько ходов дела. Делается всё, что от
|
|
81
81
|
разрешения не зависит, а несделанное называется в теле заявки, разделом об оставшемся шаге:
|
|
82
82
|
он ровно про это и написан.
|
|
83
|
+
- **Ответ на реплику владельца, пришедшую посреди хода, ход не кончает.** Выход «вопрос
|
|
84
|
+
владельцу» — про вопрос ОТ исполнителя; обратный случай под него не подходит вовсе, и
|
|
85
|
+
прочитанный так, он превращает каждую реплику владельца в конец захода. За один заход это
|
|
86
|
+
стоило трёх остановок подряд: владелец спрашивал, исполнитель отвечал и вставал.
|
|
87
|
+
- **Работа не гейтится на подтверждение, которого владелец не обещал.** «Скажи — и я сделаю»
|
|
88
|
+
переносит ход к владельцу без его согласия: он не просил, чтобы у него спрашивали, и ответа с
|
|
89
|
+
него никто не ждал. Выглядит это вежливостью, а не остановкой, и потому не читается как
|
|
90
|
+
остановка ни исполнителем, ни им.
|
|
@@ -103,7 +103,11 @@ npx agent-kit propose # отправить груз в приём: сво
|
|
|
103
103
|
cp -r node_modules/@rt-tools/agent-kit/assets /tmp/agent-kit-assets-<прежняя версия>
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
2. **Установка и раскладка.** Обычным порядком.
|
|
106
|
+
2. **Установка и раскладка.** Обычным порядком. Раскладка кладёт ту редакцию, которая **установлена**,
|
|
107
|
+
а не ту, что объявило дерево: перепутать их легко — установленная остаётся от соседней ветки,
|
|
108
|
+
где её как раз поднимали, и ложится целиком, молча, с тем же успешным выходом. Расхождение
|
|
109
|
+
точного номера раскладка отбивает сама и называет обе редакции; починка — поставить
|
|
110
|
+
зависимости и повторить вызов.
|
|
107
111
|
3. **Сверка замещённых разделов по снимку.** Какие разделы замещены, называет `doctor` — строкой
|
|
108
112
|
«замещено надстройками разделов» и перечнем «ресурс · заголовок». Каждый из них читается в
|
|
109
113
|
снимке и в новой редакции: что пакет дописал, дописывается в надстройку руками.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Находки эпика <о чём он>
|
|
2
|
+
|
|
3
|
+
<Копятся здесь, у замысла эпика: папка задачи умирает со слиянием, а находки владелец читает
|
|
4
|
+
разом, когда эпик кончился. Имя файла — имя замысла с хвостом `-findings`, и лежит он рядом с
|
|
5
|
+
самим замыслом.
|
|
6
|
+
|
|
7
|
+
Раздел на задачу, строка на находку. Каждая называет адрес — слой правил, имена этого дерева
|
|
8
|
+
или надстройку над разложенным: без адреса общее оседает в своём дереве и остаётся неизвестным
|
|
9
|
+
всем остальным.
|
|
10
|
+
|
|
11
|
+
Длина смотрится перед первой написанной строкой: раздел задачи занимает десятки строк, и предел
|
|
12
|
+
длины документа он переходит молча. Не влезает — заводится следующая часть с именем той задачи,
|
|
13
|
+
которая её завела: `<имя замысла>-findings-<КЛЮЧ>-<номер>.md`. Порядкового номера у части нет —
|
|
14
|
+
его каждое рабочее дерево видит своим, и два дерева одного эпика заводят один и тот же файл.>
|
|
15
|
+
|
|
16
|
+
## <КЛЮЧ>-<номер> — <что делала задача>
|
|
17
|
+
|
|
18
|
+
- **<Находка одной фразой — что не так, а не что надо сделать.>** <Чем подтверждена: число,
|
|
19
|
+
отказ, файл. Что это стоило.> **Адрес:** <слой правил | имена этого дерева — <что именно> |
|
|
20
|
+
надстройка над разложенным>.
|
|
21
|
+
|
|
22
|
+
## Осталось нерешённым
|
|
23
|
+
|
|
24
|
+
<Находка, по которой правки ещё не было. Названная здесь, она переезжает в закрытые вместе с
|
|
25
|
+
той правкой, которая её закрыла, — а не остаётся числиться живой.>
|
|
26
|
+
|
|
27
|
+
- **<находка>** — <почему не закрыта: ждёт решения владельца, заводится своей задачей, спорна>.
|
package/bin/agent-kit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AAuW7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU9E"}
|
package/bin/agent-kit.js
CHANGED
|
@@ -79,6 +79,9 @@ function environmentOf(root) {
|
|
|
79
79
|
return {
|
|
80
80
|
root,
|
|
81
81
|
version: manifest.version,
|
|
82
|
+
// Имя из манифеста, а не записанное здесь: по нему пакет ищет себя в зависимостях дерева,
|
|
83
|
+
// и своя копия имени разошлась бы с манифестом молча — у всякого, кто пакет переименовал.
|
|
84
|
+
name: manifest.name,
|
|
82
85
|
assetsDir: join(pkg, 'assets'),
|
|
83
86
|
// Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.
|
|
84
87
|
// У потребителя исходников рядом нет, и сверка молчит.
|