@rt-tools/agent-kit 0.5.1 → 0.5.2

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.
Files changed (72) hide show
  1. package/README.md +68 -0
  2. package/assets/commands/agent-kit-digest.md +83 -0
  3. package/assets/commands/skill-curator.md +33 -1
  4. package/assets/defaults/gate-map.sh +2 -0
  5. package/assets/defaults/project.sh +12 -1
  6. package/assets/docs/GLOSSARY.md +3 -0
  7. package/assets/hooks/docs-guard.sh +18 -1
  8. package/assets/hooks/git-guard-delivery.sh +30 -3
  9. package/assets/hooks/git-guard-main.sh +8 -0
  10. package/assets/hooks/git-guard-push-tests.sh +8 -1
  11. package/assets/hooks/grill-gate.sh +38 -16
  12. package/assets/hooks/lint-after-edit.sh +10 -3
  13. package/assets/hooks/observe.sh +90 -0
  14. package/assets/hooks/postmortem-guard.sh +92 -0
  15. package/assets/hooks/profile-check.sh +43 -0
  16. package/assets/hooks/qa-dataid-guard.sh +9 -2
  17. package/assets/hooks/reuse-first-guard.sh +9 -2
  18. package/assets/hooks/skill-gate.sh +15 -0
  19. package/assets/hooks/skill-loaded.sh +7 -0
  20. package/assets/hooks/task-context-load.sh +16 -2
  21. package/assets/hooks/task-flow-guard.sh +9 -2
  22. package/assets/hooks/window-fill-guard.sh +8 -1
  23. package/assets/laws/project-documentation.md +5 -0
  24. package/assets/laws/verifiability.md +9 -0
  25. package/assets/laws/work-conduct.md +39 -0
  26. package/assets/patterns/git-workflow-commit.azure.md +16 -12
  27. package/assets/patterns/git-workflow-commit.github.md +16 -12
  28. package/assets/patterns/git-workflow-commit.gitlab.md +16 -12
  29. package/assets/patterns/task-flow-resume.md +12 -0
  30. package/assets/patterns/task-flow-start.md +36 -2
  31. package/assets/rules/git-workflow.azure.md +15 -0
  32. package/assets/rules/git-workflow.github.md +15 -0
  33. package/assets/rules/git-workflow.gitlab.md +15 -0
  34. package/assets/rules/spec-driven.md +6 -0
  35. package/assets/rules/task-flow.md +24 -3
  36. package/assets/skills/agent-kit.md +32 -0
  37. package/assets/templates/postmortem.md +32 -0
  38. package/assets/templates/proposal.md +39 -0
  39. package/bin/agent-kit.d.ts.map +1 -1
  40. package/bin/agent-kit.js +50 -1
  41. package/bin/agent-kit.js.map +1 -1
  42. package/lib/catalog.d.ts +33 -0
  43. package/lib/catalog.d.ts.map +1 -1
  44. package/lib/catalog.js +55 -1
  45. package/lib/catalog.js.map +1 -1
  46. package/lib/commands.d.ts +41 -0
  47. package/lib/commands.d.ts.map +1 -1
  48. package/lib/commands.js +314 -3
  49. package/lib/commands.js.map +1 -1
  50. package/lib/config.d.ts +8 -0
  51. package/lib/config.d.ts.map +1 -1
  52. package/lib/config.js +4 -0
  53. package/lib/config.js.map +1 -1
  54. package/lib/observations.d.ts +72 -0
  55. package/lib/observations.d.ts.map +1 -0
  56. package/lib/observations.js +126 -0
  57. package/lib/observations.js.map +1 -0
  58. package/lib/proposals.d.ts +48 -0
  59. package/lib/proposals.d.ts.map +1 -0
  60. package/lib/proposals.js +111 -0
  61. package/lib/proposals.js.map +1 -0
  62. package/lib/submit.d.ts +24 -0
  63. package/lib/submit.d.ts.map +1 -0
  64. package/lib/submit.js +26 -0
  65. package/lib/submit.js.map +1 -0
  66. package/lib/sync.d.ts +9 -1
  67. package/lib/sync.d.ts.map +1 -1
  68. package/lib/sync.js +2 -1
  69. package/lib/sync.js.map +1 -1
  70. package/package.json +1 -1
  71. package/rt-tools-agent-kit-0.5.2.tgz +0 -0
  72. package/rt-tools-agent-kit-0.5.1.tgz +0 -0
@@ -264,30 +264,34 @@ npm run task:move -- 86 in-review
264
264
  Проверок на самом PR нет: выкатка запускается пушем в главную ветку, и до мержа никто не
265
265
  гоняет ничего. Линтеры, юниты и сценарии хуков снимает гейт пуша — ниже то, чего он не знает.
266
266
 
267
- 1. **В ветке только та правка, за которой её заводили** `git diff main...HEAD --stat`. Чужой
267
+ 1. **Главная ветка влита в эту ветку** `git fetch origin && git merge origin/main`.
268
+ Всё, что проверяется ниже, проверяется от этого основания: PR с разошедшейся ветки
269
+ показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
270
+ `git-workflow-merge`.
271
+ 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
268
272
  домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
269
- 2. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
273
+ 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
270
274
  целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
271
- 3. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
275
+ 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
272
276
  поведения он не знает — это остаётся за автором.
273
- 4. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`: сверка
277
+ 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`: сверка
274
278
  сценариев с тестами, путей в документах, раскладки либ, повторов и классов без правила.
275
279
  Какие именно есть здесь — `implementation.md` правила.
276
- 5. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет:
280
+ 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет:
277
281
  она длиннее всего, что он успевает сделать между командой и пушем.
278
- 6. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
282
+ 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
279
283
  переводится.
280
- 7. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
284
+ 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
281
285
  `browser-verification-measure`.
282
- 8. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
286
+ 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
283
287
  `seo-verify`.
284
- 9. **Тело PR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
285
- 10. **Заголовок PR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что сделано>`,
288
+ 10. **Тело PR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
289
+ 11. **Заголовок PR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что сделано>`,
286
290
  тем же номером, что стоит у задачи и в имени ветки. Инфинитив из задачи в него не
287
291
  переносится, тип и область коммита — тоже.
288
- 11. **Очередь работ сходится** — `npm run check:board`. Задача на борде, с исполнителем и
292
+ 12. **Очередь работ сходится** — `npm run check:board`. Задача на борде, с исполнителем и
289
293
  номером в заголовке; PR один на задачу, и закрывает он её целиком.
290
- 12. **Состояние PR прочитано, а не выведено из кодов возврата** — автор `<бот>`,
294
+ 13. **Состояние PR прочитано, а не выведено из кодов возврата** — автор `<бот>`,
291
295
  ревьювер — владелец, метки те же, что у задачи. Владельцу называют прочитанное.
292
296
 
293
297
  Сразу после публикации задача переставляется в разбор — `npm run task:move -- <номер>
@@ -232,26 +232,30 @@ npm run task:move -- 86 in-review
232
232
  Проверок на самом MR нет ровно до тех пор, пока конвейер не запущен, а запускается он пушем.
233
233
  Линтеры, юниты и сценарии хуков снимает гейт пуша — ниже то, чего он не знает.
234
234
 
235
- 1. **В ветке только та правка, за которой её заводили** `git diff main...HEAD --stat`. Чужой
235
+ 1. **Главная ветка влита в эту ветку** `git fetch origin && git merge origin/main`.
236
+ Всё, что проверяется ниже, проверяется от этого основания: MR с разошедшейся ветки
237
+ показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
238
+ `git-workflow-merge`.
239
+ 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
236
240
  домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
237
- 2. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
241
+ 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
238
242
  целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
239
- 3. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
243
+ 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
240
244
  поведения он не знает — это остаётся за автором.
241
- 4. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
245
+ 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
242
246
  есть здесь — `implementation.md` правила.
243
- 5. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
244
- 6. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
247
+ 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
248
+ 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
245
249
  переводится.
246
- 7. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
250
+ 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
247
251
  `browser-verification-measure`.
248
- 8. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
252
+ 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
249
253
  паттерн `seo-verify`.
250
- 9. **Описание MR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
251
- 10. **Заголовок MR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что
254
+ 10. **Описание MR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
255
+ 11. **Заголовок MR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что
252
256
  сделано>`, тем же номером, что стоит у задачи и в имени ветки.
253
- 11. **Очередь работ сходится** — `npm run check:board`.
254
- 12. **Состояние MR прочитано, а не выведено из кодов возврата.**
257
+ 12. **Очередь работ сходится** — `npm run check:board`.
258
+ 13. **Состояние MR прочитано, а не выведено из кодов возврата.**
255
259
 
256
260
  Сразу после публикации задача переставляется в разбор, и сверка очереди прогоняется ещё раз: до
257
261
  открытия MR список она не судит, а после открытия расхождение видит.
@@ -10,6 +10,8 @@ description: Паттерн правила task-flow. Брать при возв
10
10
  Паттерн правила `task-flow`. Что при этом должно быть верно — закон
11
11
  `docs/constitution/work-conduct.md`.
12
12
 
13
+ **Требует:** `hooks/task-context-load.sh`
14
+
13
15
  ## Когда брать
14
16
 
15
17
  - Сессия начата на ветке `<КЛЮЧ>-*`, работа в ней уже шла.
@@ -57,6 +59,16 @@ git log --oneline origin/main..HEAD
57
59
  - **Следующий шаг:** сценарии обоих хуков, затем подключение в настройках
58
60
  - **Незакоммиченное:** всё, ветка пока без коммитов
59
61
  - **Ждём владельца:** нет
62
+ - **Отчёт:** ещё не открыт
63
+ ```
64
+
65
+ Строка про отчёт обязательна с той минуты, как этапы кончились: между открытием отчёта и
66
+ слиянием проходит день и больше, и заход обрывается там чаще всего. Без неё следующий заход
67
+ читает «этап последний, всё зелено» и об открытом отчёте узнаёт только из истории ветки или у
68
+ владельца — то есть ровно тем пересказом, ради отмены которого всё и заведено:
69
+
70
+ ```markdown
71
+ - **Отчёт:** #1396, ждёт разбора · отвечено 3 замечания из 5 · не сделано: разбор папки задачи
60
72
  ```
61
73
 
62
74
  Решение, принятое по ходу, — вместе с причиной и с тем, что было альтернативой:
@@ -33,6 +33,13 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
33
33
 
34
34
  Находки складываются в раздел «Что уже есть в дереве» разбора.
35
35
 
36
+ Разведка кончается не ощущением, а выводом команд. До первого вопроса владельцу исполнитель
37
+ знает: как устроен репозиторий (корневая памятка), что лежит в каталоге, о котором пойдёт речь
38
+ (`ls`), и есть ли уже написанное по теме (поиск по документации и правилам). Вопрос называет,
39
+ где искали: «в таком-то месте не нашёл» — проверяемо, «не знаю» — нет. Без списка того, что
40
+ считается сделанным, разведка исполняется как настроение: прочитанный переданный текст сходит
41
+ за неё, и по текущему дереву не запускается ни одной команды.
42
+
36
43
  ### 2. Разбор с владельцем
37
44
 
38
45
  Ведёт главный агент: субагент до владельца не достучится. Команда — `/grill-me`, один вопрос
@@ -53,6 +60,24 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
53
60
  каждому вопросу добавляется свободный вариант — у закрытого набора нет строки «вопрос не тот».
54
61
  Выбор слова, имени и термина уточняется прозой в любом случае.
55
62
 
63
+ **Рамка переданного текста на текущее дерево не переносится.** Передача захода, файл
64
+ предложений и спек описывают то дерево, в котором писались. Про текущее знает только текущее:
65
+ прежде чем принять из такого текста утверждение о раскладке, оно проверяется командой здесь.
66
+ Подтверждение при этом находится само — признаки дерева, только ставящего пакет, стоят и у
67
+ дерева, которое пакет и пишет, и ставит.
68
+
69
+ Сообщение, которым исполнитель останавливается, начинается с того, чего он ждёт:
70
+
71
+ ```
72
+ Стою на выборе <что решается>. Без ответа <что будет: пойду допущением таким-то / работа стоит>.
73
+ <Вопрос>
74
+ ```
75
+
76
+ Замеры, находки ролей и список решений к этому моменту уже записаны в ход работы, и в
77
+ сообщении владельцу они лишние. Отчёт, в конце которого стоит вопрос, выглядит добросовестно
78
+ ровно настолько, насколько надёжно вопрос в нём тонет: владелец трижды переспрашивал, почему
79
+ работа стоит, и каждый круг стоил захода обоим.
80
+
56
81
  Ответы пишутся в `docs/tasks/_draft-<slug>/grill.md` — папка ещё черновик, номера нет.
57
82
 
58
83
  ```bash
@@ -90,10 +115,19 @@ npm run task:move -- <номер> in-progress
90
115
  Ветка заводится вторым вызовом: составную «завести и сразу коммитить» гард главной ветки
91
116
  отклоняет целиком.
92
117
 
93
- Остальные два файлас образца:
118
+ Номер уже выданчерновика нет и не заводится: папка задачи открывается сразу под именем
119
+ ветки, а разбор пишется в неё же. Так начинается половина работ: номер приходит прошлым
120
+ заходом, замеченным дефектом или соседней задачей, и шаг с черновиком в этом случае неисполним
121
+ целиком — переименовывать нечего, `task:new` звать незачем. Ловушка «номер не бывает первым»
122
+ сюда не относится: она про то, что задачу не заводят до разбора, а не про то, что с уже
123
+ заведённой нельзя работать.
124
+
125
+ Остальные два файла пишутся, а не кладутся образцом впрок: пустой `plan.md` на диске
126
+ неотличим от замысла, у которого нет этапов, — а следующий заход читает папку задачи первым
127
+ делом и доверяет ей. Образец открывается тем же движением, которым заполняется:
94
128
 
95
129
  ```bash
96
- cp docs/tasks/_template/plan.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/plan.md
130
+ cp docs/tasks/_template/plan.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/plan.md # и сразу пишется
97
131
  cp docs/tasks/_template/progress.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/progress.md
98
132
  ```
99
133
 
@@ -44,6 +44,10 @@ description: Правило под «Закон о поставке» для д
44
44
  `az repos pr create` с такой ветки: локально она законна, но правка из неё — это выкатка, за
45
45
  которой в очереди работ ничего не стоит. Заводится рабочий элемент, и работа переносится в
46
46
  ветку с его номером.
47
+ - **Главная ветка влита в ветку рабочего элемента до открытия PR.** Гард поставки отбивает
48
+ открытие, пока вершина главной ветки не стала предком текущей, и называет расхождение числом
49
+ коммитов. PR с разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё,
50
+ что автор проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
47
51
  - **Номер ветки и номер в заголовке PR сверяются на месте, а состояние — по доске.** Формат
48
52
  читается из текста команды и работает без сети; существование рабочего элемента, его
49
53
  состояние, исполнитель и то, что он ещё открыт, — только когда есть чем спросить. Нет сети
@@ -107,6 +111,12 @@ description: Правило под «Закон о поставке» для д
107
111
  работу вместо промаха. Держится это памятью и подсказкой, которую печатает команда заведения
108
112
  задачи. Отставшее состояние находит сверка очереди — но уже после того, как PR открыт.
109
113
 
114
+ Свежесть самой вершины главной ветки гард не проверяет: он судит по тому, что лежит в дереве, и
115
+ вершину недельной давности от сегодняшней не отличает. Сетевой вызов сюда не заводится по той же
116
+ причине, что и выше, — он падал бы вместе со связью. Поэтому гард ловит ветку, отставшую
117
+ заведомо, а `git fetch` перед вливанием стоит первым пунктом чеклиста и держится тем же, чем
118
+ держатся остальные его пункты.
119
+
110
120
  ## Паттерны
111
121
 
112
122
  - `git-workflow-commit` — рабочий элемент, ветка, коммит, пуш и PR от учётной записи машинной
@@ -138,3 +148,8 @@ description: Правило под «Закон о поставке» для д
138
148
  записи, на следующий вызов это не переносится: PR открывают токеном учётной записи машинной
139
149
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
140
150
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
151
+ - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
152
+ разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
153
+ входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
154
+ которому нужен ключ. Что именно переносится руками, названо списком в компаньоне правила, и
155
+ список пополняется тем же движением, которым заводится новый файл вне индекса.
@@ -44,6 +44,10 @@ description: Правило под «Закон о поставке» для д
44
44
  - **Ветка без номера задачи PR не открывает.** Гард поставки отбивает `gh pr create` с такой
45
45
  ветки: локально она законна, но правка из неё — это выкатка, за которой в очереди работ
46
46
  ничего не стоит. Заводится задача, и работа переносится в ветку с её номером.
47
+ - **Главная ветка влита в ветку задачи до открытия PR.** Гард поставки отбивает открытие, пока
48
+ вершина главной ветки не стала предком текущей, и называет расхождение числом коммитов. PR с
49
+ разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё, что автор
50
+ проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
47
51
  - **Ключ задач задаётся один раз, и все три формы имени выводятся из него.** Заголовок задачи,
48
52
  имя ветки и заголовок отчёта строит один и тот же ключ: команда заведения задачи собирает по
49
53
  нему заголовок, гард поставки достаёт по нему номер из имени ветки, сверка очереди — из
@@ -115,6 +119,12 @@ description: Правило под «Закон о поставке» для д
115
119
  работу вместо промаха. Держится это памятью и подсказкой, которую печатает команда заведения
116
120
  задачи. Отставшую колонку находит сверка очереди — но уже после того, как PR открыт.
117
121
 
122
+ Свежесть самой вершины главной ветки гард не проверяет: он судит по тому, что лежит в дереве, и
123
+ вершину недельной давности от сегодняшней не отличает. Сетевой вызов сюда не заводится по той же
124
+ причине, что и выше, — он падал бы вместе со связью. Поэтому гард ловит ветку, отставшую
125
+ заведомо, а `git fetch` перед вливанием стоит первым пунктом чеклиста и держится тем же, чем
126
+ держатся остальные его пункты.
127
+
118
128
  ## Паттерны
119
129
 
120
130
  - `git-workflow-commit` — задача, ветка, коммит, пуш и PR от учётной записи машинной работы.
@@ -144,3 +154,8 @@ description: Правило под «Закон о поставке» для д
144
154
  записи, на следующий вызов это не переносится: PR открывают токеном учётной записи машинной
145
155
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
146
156
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
157
+ - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
158
+ разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
159
+ входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
160
+ которому нужен ключ. Что именно переносится руками, названо списком в компаньоне правила, и
161
+ список пополняется тем же движением, которым заводится новый файл вне индекса.
@@ -43,6 +43,10 @@ description: Правило под «Закон о поставке» для д
43
43
  - **Ветка без номера задачи MR не открывает.** Гард поставки отбивает `glab mr create` с такой
44
44
  ветки: локально она законна, но правка из неё — это выкатка, за которой в очереди работ
45
45
  ничего не стоит. Заводится задача, и работа переносится в ветку с её номером.
46
+ - **Главная ветка влита в ветку задачи до открытия MR.** Гард поставки отбивает открытие, пока
47
+ вершина главной ветки не стала предком текущей, и называет расхождение числом коммитов. MR с
48
+ разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё, что автор
49
+ проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
46
50
  - **Номер ветки и номер в заголовке MR сверяются на месте, а состояние задачи — по доске.**
47
51
  Формат читается из текста команды и работает без сети; существование задачи, её метка
48
52
  списка, исполнитель и то, что она ещё открыта, — только когда есть чем спросить. Нет сети
@@ -105,6 +109,12 @@ description: Правило под «Закон о поставке» для д
105
109
  работу вместо промаха. Держится это памятью и подсказкой, которую печатает команда заведения
106
110
  задачи. Отставший список находит сверка очереди — но уже после того, как MR открыт.
107
111
 
112
+ Свежесть самой вершины главной ветки гард не проверяет: он судит по тому, что лежит в дереве, и
113
+ вершину недельной давности от сегодняшней не отличает. Сетевой вызов сюда не заводится по той же
114
+ причине, что и выше, — он падал бы вместе со связью. Поэтому гард ловит ветку, отставшую
115
+ заведомо, а `git fetch` перед вливанием стоит первым пунктом чеклиста и держится тем же, чем
116
+ держатся остальные его пункты.
117
+
108
118
  ## Паттерны
109
119
 
110
120
  - `git-workflow-commit` — задача, ветка, коммит, пуш и MR от учётной записи машинной работы.
@@ -134,3 +144,8 @@ description: Правило под «Закон о поставке» для д
134
144
  записи, на следующий вызов это не переносится: MR открывают токеном учётной записи машинной
135
145
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
136
146
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
147
+ - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
148
+ разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
149
+ входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
150
+ которому нужен ключ. Что именно переносится руками, названо списком в компаньоне правила, и
151
+ список пополняется тем же движением, которым заводится новый файл вне индекса.
@@ -103,6 +103,12 @@ description: Правило под «Закон о документации пр
103
103
  - **Спек объявляет законы, которые применяет, и связь сверяется в обе стороны.** Закон,
104
104
  названный в тексте спека, обязан стоять в шапке: иначе по закону не узнать, какие домены
105
105
  на нём стоят.
106
+ - **Переносимый текст говорит о соседнем ресурсе условно и называет его по имени.** Что
107
+ разложено в дереве, а что нет, знает список раскладки, а не текст ресурса. Сказанное
108
+ безусловно — «правку кода до этого отбивает гард» — приходит в контекст каждой сессии и врёт
109
+ про дерево, где того гарда не разложили; поправить это дерево не может ничем, если у ресурса
110
+ нет надстройки. Требование ресурса к ресурсу при этом объявляется строкой в шапке, а не
111
+ выводится из такой фразы.
106
112
 
107
113
  ## Чего из закона здесь нет
108
114
 
@@ -11,6 +11,8 @@ description: Правило под «Закон о ведении работы»
11
11
  про ход работы; здесь — чем это названо в этом дереве, где лежит и что из закона у нас не
12
12
  проверяется.
13
13
 
14
+ **Требует:** `hooks/task-flow-guard.sh`, `hooks/task-context-load.sh`, `hooks/grill-gate.sh`, `hooks/window-fill-guard.sh`
15
+
14
16
  ## Как это называется здесь
15
17
 
16
18
  | В законе | Здесь |
@@ -76,6 +78,15 @@ description: Правило под «Закон о ведении работы»
76
78
  законов или правил, поиск по ним. Отбивает гард разговора — на завершении хода, а не на
77
79
  инструменте вопроса: спрашивают чаще прозой, чем меню. Найденное ложится в раздел «Что уже
78
80
  сказано в правилах» разбора.
81
+ - **Действия, которые исполнитель не делает без слова владельца, перечислены в компаньоне
82
+ правила.** Список у каждого дерева свой — пакет знает только требование, чтобы список был
83
+ назван. Не названный, он выводится из общих слов, и «делай, что нужно по плану» становится
84
+ разрешением на пуш и правку общих документов заодно с коммитом.
85
+ - **Ход, в котором исполнитель признал промах, не заканчивается, пока записи о происшествии
86
+ нет.** Отбивает гард происшествия — на завершении хода: к моменту признания промах уже
87
+ случился, и ловить раньше нечего. Признание ловится набором образцов, а не пониманием смысла;
88
+ промах, признанный словами вне набора, гард пропускает, и это его известная граница, а не
89
+ обещание.
79
90
  - **Состояние незаконченной работы приходит в контекст на запуске сессии.** Замысел и ход
80
91
  работы отдаются целиком, разбор просьбы — путём. Ветка вида `<КЛЮЧ>-*` без папки даёт
81
92
  предупреждение с готовой командой, но сессию не рвёт.
@@ -135,6 +146,12 @@ description: Правило под «Закон о ведении работы»
135
146
  обязательных вопросов, ни о том, ответил ли на них владелец. Образец разбора перечисляет их
136
147
  таблицей, но пустая таблица проходит так же, как заполненная.
137
148
 
149
+ Гард разговора судит завершение хода, а не отправку вопроса. К моменту отказа вопрос уже у
150
+ владельца, и владелец видит его вместе с отбитым ходом: требование срабатывает, но исполняется
151
+ задним числом. Прозаический вопрос инструментом не является, и раньше поймать его нечем.
152
+ Отсюда порядок: правило работы читается первым движением захода, до первой реплики владельцу,
153
+ а не по отказу гарда; гард отмечает пропуск, но не отменяет его.
154
+
138
155
  Неизменность замысла не стережёт ничто: `plan.md` правится тем же инструментом, что и
139
156
  остальные тексты, и правка по ходу отличима от первоначальной записи только по истории.
140
157
  Держится это тем же, чем и порядок разбора.
@@ -170,9 +187,13 @@ description: Правило под «Закон о ведении работы»
170
187
  договорённость обязана его пережить: её сценарии получают номера в общей нумерации домена,
171
188
  и на них ссылаются заголовки тестов. Обратное тоже верно — ход работы не кладётся в
172
189
  `proposed/`: спек, в котором завелись шаги, снова становится планом и умирает после мержа.
173
- - **Меню вариантов на разборе годится только для выбора значения из закрытого набора.** Пока
174
- постановка вопроса не подтверждена, спрашивается прозой: у меню нет строки «вопрос не тот».
175
- Выбор слова, имени и термина узким вопросом не является никогда.
190
+ - **У меню нет строки «вопрос не тот».** Меню годится для выбора значения из закрытого набора;
191
+ пока постановка вопроса не подтверждена, отвергнуть её владельцу нечем он выбирает из
192
+ вариантов, выведенных из неверной посылки. Настройки владельца, требующие меню, требование
193
+ не снимают: тогда к каждому вопросу добавляется свободный вариант, и он же — единственное
194
+ место, где вопрос отвергается целиком. Три вопроса ушли одним меню, у одного постановка была
195
+ ложной, и сказать «вопрос не тот» было нечем. Выбор слова, имени и термина узким вопросом не
196
+ является никогда.
176
197
  - **Субагент вопросов владельцу не задаёт.** Ни роли, ни конвейер до него не достучатся —
177
198
  они возвращают текст главному агенту. Поэтому разбор ведёт главный агент, а роли стоят по
178
199
  обе стороны от него.
@@ -44,8 +44,35 @@ description: Переносимый слой правил агента — за
44
44
  npx agent-kit doctor # что разложено, что отстало, что лежит от отказанного
45
45
  npx agent-kit sync # разложить
46
46
  npx agent-kit sync --check # ничего не писать, отказать при расхождении
47
+ npx agent-kit stats # чем пользовались, чем ни разу, обо что спотыкались
48
+ npx agent-kit propose # отправить предложения, адресованные пакету
47
49
  ```
48
50
 
51
+ ## Обратная связь наверх
52
+
53
+ Слой правил правится не по памяти, а по тому, как им пользовались. Держится это тремя вещами.
54
+
55
+ **Наблюдения** пишут сами гарды — в `.claude/rt-kit/observations/`, файлом на день. В строке
56
+ имя ресурса пакета, род события, род правки, версия и признак сессии; путей дерева, имён его
57
+ доменов и его собственного имени там нет. Выключаются ключом `"observe": false` в конфиге.
58
+
59
+ **Сводка** — `agent-kit stats`. Самая ценная её строка не «чем пользовались», а **что разложено
60
+ и не загружено ни разу**: правило, которого никто не открыл, ничем себя не выдаёт.
61
+
62
+ **Предложения** приносит разбор закрытой задачи — командой `/skill-curator`. Каждому он ставит
63
+ адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
64
+ (форма — шаблон `proposal.md`), а `agent-kit propose` отправляет наружу те, что адресованы
65
+ пакету, вместе со сводкой. Текст с адресом этого дерева отбивает отправку целиком.
66
+
67
+ Разбираются они в репозитории самого пакета — командой `/agent-kit-digest`, там же, где лежат
68
+ правимые ресурсы и видно всех потребителей сразу.
69
+
70
+ Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой
71
+ не приходит: замечание было прочитано, процитировано владельцу и нарушено в том же ходе —
72
+ цитата не становится правилом от того, что её произнесли. Закрытым предложение считается,
73
+ только войдя в ресурс пакета; до этого на него не ссылаются как на действующее требование и не
74
+ считают дырку закрытой.
75
+
49
76
  ## Установка туда, где уже всё своё
50
77
 
51
78
  1. `init`, затем `skip` на всё, что дерево держит само. Пустая раскладка — законное начало.
@@ -83,3 +110,8 @@ npx agent-kit sync --check # ничего не писать, отказать
83
110
  - **Утверждение правила переезжает вместе с кодом.** Вынесенное в надстройку перестаёт
84
111
  находиться по прежнему символу, и привязка в спутнике правила врёт молча — сверка спеков
85
112
  ловит это, но только если её позвать.
113
+ - **Признак по подстроке пути судит и то, что лежит вне дерева.** Гарды отдают в профиль
114
+ абсолютный путь целиком, и образец вида `*/projects/*` совпадает с домашним каталогом агента
115
+ ровно так же, как с кодом дерева: запись в файл вне репозитория была отбита гардом хода
116
+ работы с требованием замысла, к ней не относящегося. Путь в профиле сначала приводится к
117
+ корню дерева, и всё, что вне корня, признака не получает.
@@ -0,0 +1,32 @@
1
+ # <чем был промах, а не на какой задаче случился>
2
+
3
+ <дата>. <Одна строка: где шла работа и до чего она дошла.>
4
+
5
+ ## Что произошло
6
+
7
+ <Что исполнитель сделал и чем это было неверно. Без оценок: разбирается механизм, а не
8
+ намерение.>
9
+
10
+ ## Механизм промаха
11
+
12
+ 1. <что принято за данность>
13
+ 2. <откуда взято>
14
+ 3. <чем подтверждено — и почему подтверждение оказалось ложным>
15
+ 4. <что сделано дальше>
16
+
17
+ ## Что было доступно до промаха
18
+
19
+ - <файл, команда или уже прочитанное, где лежал ответ>
20
+
21
+ Отсюда видно, промах это или нехватка данных.
22
+
23
+ ## Чем ловилось
24
+
25
+ - **Слоем правил —** <что отбило, что промолчало>.
26
+ - **Гардом —** <сработал, не сработал, сработал поздно>.
27
+ - **Владельцем —** <заметил сразу, заметил на приёмке, не заметил>.
28
+
29
+ ## Что ушло в слой правил
30
+
31
+ <Предложение с адресом либо правка закона, правила, паттерна — с именами. Запись без этого
32
+ раздела закрытой не считается: разбор, из которого ничего не вышло, — жалоба.>
@@ -0,0 +1,39 @@
1
+ # Предложения по слою правил
2
+
3
+ <!--
4
+ Кладёт этот файл главный агент — шагом команды `/skill-curator`, из ответа роли разбора. Роль
5
+ файлов не пишет: правила действуют на все будущие сессии, и менять их молча нельзя.
6
+
7
+ Читает файл `agent-kit propose`. Форма заголовка — не украшение: по ней команда отбирает то,
8
+ что уезжает в репозиторий пакета.
9
+
10
+ ## <адрес> · <ресурс>
11
+
12
+ Адрес один из трёх, и ставит его роль:
13
+
14
+ пакет — правка ресурса @rt-tools/agent-kit; уезжает наружу
15
+ компаньон — implementation.md рядом с правилом: имена этого дерева
16
+ дерево — надстройка этого дерева; наружу не уезжает никогда
17
+
18
+ Ресурс называется идентификатором пакета — `rules/styling-bem.md`, `hooks/skill-gate.sh`, — а у
19
+ адресов «компаньон» и «дерево» путём в дереве.
20
+
21
+ В тексте предложения не бывает ни путей этого дерева, ни имён его доменов, ни его собственного
22
+ имени: файл уезжает в чужой репозиторий целиком. Найденный адрес дерева отбивает отправку с
23
+ номером строки — это проверка, а не напоминание.
24
+ -->
25
+
26
+ ## пакет · rules/<правило>.md
27
+
28
+ - **место:** раздел «<заголовок>», в конец
29
+ - **повод:** что в этой задаче пошло не так без этого правила
30
+
31
+ > Готовый текст правки — ровно то, что вставить, в стиле соседних правил: по-русски,
32
+ > утверждением, без воды.
33
+
34
+ ## дерево · .claude/rt-kit/gate-map.sh
35
+
36
+ - **место:** ветка `edit`, рядом с соседним родом файлов
37
+ - **повод:** свой род файлов, которого у других деревьев нет
38
+
39
+ > Готовый текст правки.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAaA,OAAO,EAAqC,iBAAiB,EAAc,MAAM,oBAAoB,CAAC;AAoKtG,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqC9E"}
1
+ {"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAcA,OAAO,EAAqC,iBAAiB,EAA8B,MAAM,oBAAoB,CAAC;AA6LtH,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiE9E"}
package/bin/agent-kit.js CHANGED
@@ -5,12 +5,15 @@
5
5
  * спеками — кроме одного, чего команде знать не по чину: откуда взялся выбор законов. У строки
6
6
  * запуска это флаг, у терминала — вопрос, у прогона без терминала нет ни того ни другого.
7
7
  */
8
+ import { execFileSync } from 'node:child_process';
8
9
  import { readFileSync } from 'node:fs';
9
10
  import { dirname, join, resolve } from 'node:path';
10
11
  import { fileURLToPath } from 'node:url';
11
12
  import process from 'node:process';
12
13
  import { readCatalog, resolveSelection } from '../lib/catalog.js';
13
- import { adopt, doctor, init, list, sync } from '../lib/commands.js';
14
+ import { adopt, doctor, init, list, propose, stats, sync } from '../lib/commands.js';
15
+ import { DEFAULT_DAYS } from '../lib/observations.js';
16
+ import { ghIssue, repositoryOf } from '../lib/submit.js';
14
17
  import { staleBuild } from '../lib/freshness.js';
15
18
  import { packageRootFrom } from '../lib/package-root.js';
16
19
  import { readAxes } from '../lib/variants.js';
@@ -23,6 +26,11 @@ const USAGE = [
23
26
  ' sync разложить ресурсы пакета в дерево проекта',
24
27
  ' sync --check ничего не писать, отказать при расхождении — для гейта пуша',
25
28
  ' doctor рассказать о состоянии раскладки, ничего не меняя',
29
+ ' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',
30
+ ' stats --days N за сколько дней; без довода — за три',
31
+ ' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',
32
+ ' propose отправить предложения с адресом «пакет» в очередь работ пакета',
33
+ ' propose --dry-run показать, что уехало бы, и ничего не отправлять',
26
34
  ' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',
27
35
  '',
28
36
  ' --root <путь> корень проекта; по умолчанию текущий каталог',
@@ -53,8 +61,23 @@ function environmentOf(root) {
53
61
  // Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.
54
62
  // У потребителя исходников рядом нет, и сверка молчит.
55
63
  stale: staleBuild(pkg, manifest.name),
64
+ // Куда уезжают предложения. Читается из манифеста: зашитый в код адрес назвал бы чужое
65
+ // дерево в текстах пакета — и врал бы у всякого, кто пакет форкнул.
66
+ repository: repositoryOf(manifest.repository?.url ?? ''),
56
67
  };
57
68
  }
69
+ /** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */
70
+ function remoteOf(root) {
71
+ try {
72
+ return execFileSync('git', ['-C', root, 'remote', 'get-url', 'origin'], {
73
+ encoding: 'utf8',
74
+ stdio: ['ignore', 'pipe', 'ignore'],
75
+ }).trim();
76
+ }
77
+ catch {
78
+ return '';
79
+ }
80
+ }
58
81
  function optionOf(argv, name, fallback) {
59
82
  const index = argv.indexOf(name);
60
83
  return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;
@@ -168,6 +191,32 @@ export async function main(argv) {
168
191
  return list(env);
169
192
  case 'sync':
170
193
  return sync(env, argv.includes('--check'));
194
+ case 'stats': {
195
+ const spoken = Number(optionOf(argv, '--days', ''));
196
+ return stats(env, {
197
+ days: Number.isFinite(spoken) && spoken > 0 ? Math.floor(spoken) : DEFAULT_DAYS,
198
+ // Сегодняшний день берётся здесь: у команды своих часов нет, иначе сводку за
199
+ // отрезок не проверить спекой — вчерашняя фикстура завтра станет позавчерашней.
200
+ today: new Date().toISOString().slice(0, 10),
201
+ json: argv.includes('--json'),
202
+ });
203
+ }
204
+ case 'propose': {
205
+ // Сводка едет вместе с предложением: без цифр оно читается как мнение. Берётся тем
206
+ // же отрезком, что и сводка по умолчанию, — предложение пишут по свежей задаче.
207
+ const summary = stats(env, {
208
+ days: DEFAULT_DAYS,
209
+ today: new Date().toISOString().slice(0, 10),
210
+ json: false,
211
+ });
212
+ return propose(env, {
213
+ dryRun: argv.includes('--dry-run'),
214
+ submit: ghIssue,
215
+ repository: env.repository ?? '',
216
+ remote: remoteOf(env.root),
217
+ summary: summary.lines,
218
+ });
219
+ }
171
220
  case 'doctor':
172
221
  return doctor(env);
173
222
  case 'adopt':