@rt-tools/agent-kit 0.3.0 → 0.4.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.
Files changed (201) hide show
  1. package/README.md +194 -30
  2. package/assets/agents/business-analyst.md +74 -0
  3. package/assets/agents/project-manager.md +70 -0
  4. package/assets/agents/qa-engineer.md +72 -0
  5. package/assets/agents/skill-curator.md +110 -0
  6. package/assets/agents/spec-critic.md +44 -0
  7. package/assets/agents/spec-writer.md +50 -0
  8. package/assets/checks/board.github.mjs +286 -0
  9. package/assets/checks/check-board.github.mjs +188 -0
  10. package/assets/checks/check-doc-paths.mjs +163 -0
  11. package/assets/checks/check-dupes.mjs +277 -0
  12. package/assets/checks/check-lib-layers.mjs +573 -0
  13. package/assets/checks/check-reuse.mjs +208 -0
  14. package/assets/checks/check-schema-drift.mjs +186 -0
  15. package/assets/checks/check-specs.mjs +1007 -0
  16. package/assets/checks/check-styles.mjs +109 -0
  17. package/assets/checks/rt-kit-checks.config.mjs +134 -0
  18. package/assets/checks/task-new.github.mjs +198 -0
  19. package/assets/commands/skill-curator.md +70 -0
  20. package/assets/defaults/gate-map.sh +100 -0
  21. package/assets/defaults/project.sh +179 -0
  22. package/assets/hooks/browser-device-id.sh +0 -0
  23. package/assets/hooks/browser-guard-device-id.sh +2 -1
  24. package/assets/hooks/browser-guard-no-asking.sh +27 -0
  25. package/assets/hooks/browser-guard-no-listing.sh +2 -1
  26. package/assets/hooks/browser-guard-no-other-drivers.sh +2 -1
  27. package/assets/hooks/browser-guard-require-select.sh +2 -1
  28. package/assets/hooks/commit-msg.sh +1 -1
  29. package/assets/hooks/constitution-index.sh +5 -4
  30. package/assets/hooks/dev-server-guard.sh +8 -6
  31. package/assets/hooks/docs-guard.sh +223 -37
  32. package/assets/hooks/git-guard-delivery.sh +86 -29
  33. package/assets/hooks/git-guard-main.sh +1 -0
  34. package/assets/hooks/git-guard-push-tests.sh +34 -13
  35. package/assets/hooks/glossary-load.sh +23 -0
  36. package/assets/hooks/lint-after-edit.sh +155 -30
  37. package/assets/hooks/qa-dataid-guard.sh +72 -32
  38. package/assets/hooks/reuse-first-guard.sh +105 -34
  39. package/assets/hooks/skill-gate-rearm.sh +1 -0
  40. package/assets/hooks/skill-gate.sh +75 -15
  41. package/assets/hooks/skill-loaded.sh +1 -0
  42. package/assets/hooks/sql-guard.sh +606 -56
  43. package/assets/hooks/task-context-load.sh +100 -0
  44. package/assets/hooks/task-flow-guard.sh +107 -0
  45. package/assets/laws/{access.md → application/access.md} +1 -4
  46. package/assets/laws/{locales.md → application/locales.md} +1 -3
  47. package/assets/laws/application/money.md +41 -0
  48. package/assets/laws/application/ownership.md +32 -0
  49. package/assets/laws/{search-visibility.md → application/search-visibility.md} +1 -1
  50. package/assets/laws/code-structure.md +7 -6
  51. package/assets/laws/delivery.md +53 -3
  52. package/assets/laws/entity-editing.md +49 -55
  53. package/assets/laws/entity-models.md +4 -14
  54. package/assets/laws/frontend-application.md +5 -5
  55. package/assets/laws/lib-imports.md +14 -1
  56. package/assets/laws/lists.md +33 -0
  57. package/assets/laws/navigation.md +40 -0
  58. package/assets/laws/project-documentation.md +17 -8
  59. package/assets/laws/reuse-first.md +26 -21
  60. package/assets/laws/shared-code.md +13 -1
  61. package/assets/laws/verifiability.md +17 -1
  62. package/assets/laws/work-conduct.md +48 -0
  63. package/assets/patterns/admin-lists-screen.md +131 -0
  64. package/assets/patterns/admin-nav-item.md +71 -0
  65. package/assets/patterns/angular-patterns-state.md +29 -22
  66. package/assets/patterns/api-layer-pair.md +40 -30
  67. package/assets/patterns/browser-verification-measure.md +41 -38
  68. package/assets/patterns/browser-verification-stand.md +106 -42
  69. package/assets/patterns/component-structure-new.md +33 -32
  70. package/assets/patterns/dependencies-upgrade.md +65 -0
  71. package/assets/patterns/doc-style-sweep.md +65 -28
  72. package/assets/patterns/doc-style-write.md +36 -33
  73. package/assets/patterns/entity-aside.md +136 -0
  74. package/assets/patterns/entity-models-new.md +124 -0
  75. package/assets/patterns/entity-store.md +91 -0
  76. package/assets/patterns/git-workflow-commit.azure.md +259 -0
  77. package/assets/patterns/git-workflow-commit.github.md +333 -0
  78. package/assets/patterns/git-workflow-commit.gitlab.md +283 -0
  79. package/assets/patterns/git-workflow-merge.md +42 -25
  80. package/assets/patterns/git-workflow-migration.md +61 -31
  81. package/assets/patterns/git-workflow-restart.md +20 -20
  82. package/assets/patterns/lib-layers-move.md +50 -32
  83. package/assets/patterns/lib-layers-new.md +41 -29
  84. package/assets/patterns/ownership-scope-resolve.md +69 -0
  85. package/assets/patterns/permissions-procedure.md +35 -33
  86. package/assets/patterns/platform-access-di.md +39 -25
  87. package/assets/patterns/pricing-quote.md +71 -0
  88. package/assets/patterns/reuse-first-extend.md +22 -22
  89. package/assets/patterns/seo-page.md +52 -40
  90. package/assets/patterns/seo-verify.md +48 -29
  91. package/assets/patterns/shared-code-new.md +37 -31
  92. package/assets/patterns/spec-driven-domain.md +44 -37
  93. package/assets/patterns/spec-driven-rule.md +55 -40
  94. package/assets/patterns/styling-bem-component.md +43 -32
  95. package/assets/patterns/styling-bem-layout.md +30 -24
  96. package/assets/patterns/task-flow-close.md +90 -0
  97. package/assets/patterns/task-flow-resume.md +94 -0
  98. package/assets/patterns/task-flow-start.md +117 -0
  99. package/assets/patterns/testing-e2e.md +53 -51
  100. package/assets/patterns/testing-unit.md +70 -46
  101. package/assets/patterns/translations-key.md +32 -19
  102. package/assets/patterns/ts-procedure.md +24 -25
  103. package/assets/rules/angular-patterns.md +46 -27
  104. package/assets/rules/api-layer.md +46 -28
  105. package/assets/rules/browser-verification.md +66 -48
  106. package/assets/rules/component-structure.md +43 -27
  107. package/assets/rules/dependencies.md +66 -0
  108. package/assets/rules/doc-style.md +81 -39
  109. package/assets/rules/entity-conventions.md +78 -0
  110. package/assets/rules/entity-models.md +70 -0
  111. package/assets/rules/git-workflow.azure.md +116 -0
  112. package/assets/rules/git-workflow.github.md +123 -0
  113. package/assets/rules/git-workflow.gitlab.md +113 -0
  114. package/assets/rules/lib-layers.md +56 -30
  115. package/assets/rules/lists.md +73 -0
  116. package/assets/rules/navigation.md +78 -0
  117. package/assets/rules/ownership-scope.md +63 -0
  118. package/assets/rules/permissions.md +43 -25
  119. package/assets/rules/platform-access.md +57 -29
  120. package/assets/rules/pricing.md +64 -0
  121. package/assets/rules/reuse-first.md +57 -43
  122. package/assets/rules/seo.md +51 -30
  123. package/assets/rules/shared-code.md +51 -26
  124. package/assets/rules/spec-driven.md +96 -50
  125. package/assets/rules/styling-bem.md +54 -39
  126. package/assets/rules/task-flow.md +110 -0
  127. package/assets/rules/testing.md +78 -47
  128. package/assets/rules/translations.md +48 -31
  129. package/assets/rules/typescript-conventions.md +57 -27
  130. package/assets/skills/agent-kit.md +81 -0
  131. package/assets/skills/write-a-skill.md +108 -0
  132. package/assets/templates/gate-map.sh +23 -15
  133. package/assets/templates/implementation.md +14 -8
  134. package/assets/templates/pattern.md +1 -1
  135. package/assets/templates/project.sh +32 -19
  136. package/assets/templates/rule.md +1 -1
  137. package/assets/variants.json +20 -0
  138. package/assets/workflows/feature.js +134 -0
  139. package/assets/workflows/plan.js +150 -0
  140. package/bin/agent-kit.d.ts.map +1 -1
  141. package/bin/agent-kit.js +78 -5
  142. package/bin/agent-kit.js.map +1 -1
  143. package/bin/prompt.d.ts +5 -0
  144. package/bin/prompt.d.ts.map +1 -1
  145. package/bin/prompt.js +19 -7
  146. package/bin/prompt.js.map +1 -1
  147. package/index.d.ts +1 -0
  148. package/index.d.ts.map +1 -1
  149. package/index.js +1 -0
  150. package/index.js.map +1 -1
  151. package/lib/assets.d.ts +8 -3
  152. package/lib/assets.d.ts.map +1 -1
  153. package/lib/assets.js +13 -3
  154. package/lib/assets.js.map +1 -1
  155. package/lib/catalog.d.ts +52 -5
  156. package/lib/catalog.d.ts.map +1 -1
  157. package/lib/catalog.js +104 -16
  158. package/lib/catalog.js.map +1 -1
  159. package/lib/commands.d.ts +22 -1
  160. package/lib/commands.d.ts.map +1 -1
  161. package/lib/commands.js +202 -14
  162. package/lib/commands.js.map +1 -1
  163. package/lib/companion.d.ts +5 -1
  164. package/lib/companion.d.ts.map +1 -1
  165. package/lib/companion.js +29 -2
  166. package/lib/companion.js.map +1 -1
  167. package/lib/config.d.ts +26 -9
  168. package/lib/config.d.ts.map +1 -1
  169. package/lib/config.js +41 -15
  170. package/lib/config.js.map +1 -1
  171. package/lib/freshness.d.ts +14 -0
  172. package/lib/freshness.d.ts.map +1 -0
  173. package/lib/freshness.js +116 -0
  174. package/lib/freshness.js.map +1 -0
  175. package/lib/hooks-map.d.ts +24 -0
  176. package/lib/hooks-map.d.ts.map +1 -0
  177. package/lib/hooks-map.js +72 -0
  178. package/lib/hooks-map.js.map +1 -0
  179. package/lib/integrity.d.ts +36 -0
  180. package/lib/integrity.d.ts.map +1 -0
  181. package/lib/integrity.js +44 -0
  182. package/lib/integrity.js.map +1 -0
  183. package/lib/picker.d.ts +11 -1
  184. package/lib/picker.d.ts.map +1 -1
  185. package/lib/picker.js +44 -6
  186. package/lib/picker.js.map +1 -1
  187. package/lib/sync.d.ts +26 -0
  188. package/lib/sync.d.ts.map +1 -1
  189. package/lib/sync.js +59 -4
  190. package/lib/sync.js.map +1 -1
  191. package/lib/variants.d.ts +44 -0
  192. package/lib/variants.d.ts.map +1 -0
  193. package/lib/variants.js +82 -0
  194. package/lib/variants.js.map +1 -0
  195. package/package.json +1 -1
  196. package/rt-tools-agent-kit-0.4.0.tgz +0 -0
  197. package/assets/laws/admin-lists.md +0 -35
  198. package/assets/laws/admin-navigation.md +0 -38
  199. package/assets/patterns/git-workflow-commit.md +0 -175
  200. package/assets/rules/git-workflow.md +0 -106
  201. package/rt-tools-agent-kit-0.3.0.tgz +0 -0
@@ -1,37 +1,45 @@
1
1
  #!/usr/bin/env bash
2
- # Карта «что правится какое правило» этого дерева. Её читает хук гейта правил.
2
+ # Надстройка карты гейта: то, чего нет у других деревьев мастерской.
3
3
  #
4
- # Живёт в проекте, а не в пакете: имена каталогов, расширения и команды поставки у каждого
5
- # дерева свои. Пакет везёт механизм, проект карту.
4
+ # Скопировать в `.claude/rt-kit/gate-map.sh` и дописать своё. Файл необязателен: без него
5
+ # действует умолчание пакета `.claude/rt-kit/defaults/gate-map.sh`, где уже разобраны тесты,
6
+ # компоненты, стили, барели, манифесты, документы и команды поставки.
6
7
  #
7
- # Функция печатает ИМЯ ПРАВИЛА или молчит. Молчание «правила на это нет», и гейт пропускает.
8
+ # Заводить эту надстройку стоит ровно тогда, когда у дерева есть род файлов, которого нет у
9
+ # остальных: витрина, свой генератор, чужая раскладка каталогов.
8
10
  #
9
- # Порядок веток решает: первое совпадение выигрывает, поэтому частное идёт раньше общего.
10
- # Файл спеки не файл компонента, и обе ветки обязаны стоять до общей ветки расширения.
11
+ # Функция печатает ИМЯ ПРАВИЛА или молчит. Имён может быть несколько, по одному в строке.
12
+ # Порядок веток решает: первое совпадение выигрывает, поэтому частное идёт раньше общего и
13
+ # своё частное обязано стоять ДО вызова умолчания, иначе общая ветка расширения его перехватит.
11
14
 
12
15
  skill_for() {
13
16
  kind="$1"
14
17
  target="$2"
18
+ written="$3"
15
19
 
16
20
  case "$kind" in
17
21
  edit)
18
22
  case "$target" in
19
- # Файлы самого агента правятся без правила: правило на них — это оно само.
20
- */.claude/*) return 0 ;;
21
- *.spec.ts) printf '%s' '<правило про тесты>' ;;
22
- *.component.ts|*.component.html) printf '%s' '<правило про компонент>' ;;
23
- *.scss) printf '%s' '<правило про оформление>' ;;
24
- */index.ts) printf '%s' '<правило про раскладку либ>' ;;
25
- *.ts) printf '%s' '<правило про код>' ;;
26
- *.md) printf '%s' '<правило про тексты>' ;;
23
+ # Пример: у витрины своё правило, пакет такого не везёт.
24
+ # *.stories.ts | *.mdx) printf '%s\n' '<правило витрины>' ; return 0 ;;
25
+
26
+ # Пример: домен, который правится по своему правилу.
27
+ # */libs/<домен>/*) printf '%s\n' '<правило домена>' ; return 0 ;;
28
+ *) ;;
27
29
  esac
28
30
  ;;
29
31
  bash)
30
32
  case "$target" in
31
- *git\ commit*|*git\ push*|*gh\ pr\ create*) printf '%s' '<правило про поставку>' ;;
33
+ # Пример: своя команда развёртывания.
34
+ # *<команда>*) printf '%s\n' '<правило>' ; return 0 ;;
35
+ *) ;;
32
36
  esac
33
37
  ;;
34
38
  esac
35
39
 
40
+ # Всё, что дерево не назвало своим, разбирает умолчание пакета. Проверка на объявленность
41
+ # нужна ровно в одном промежутке: пакет обновлён, а `sync` в этом дереве ещё не прогнан.
42
+ command -v skill_for_default >/dev/null 2>&1 && skill_for_default "$kind" "$target" "$written"
43
+
36
44
  return 0
37
45
  }
@@ -1,14 +1,20 @@
1
- # <имя-правила> — как это устроено здесь
1
+ # <имя-правила> — что здесь своё
2
2
 
3
- Имена этого дерева при правиле `SKILL.md` рядом. Отдельный файл потому, что правило говорит
4
- приёмом и переносится между репозиториями целиком, а всё, что ниже, верно только здесь и
5
- устаревает при каждом переименовании.
3
+ Имена и привязки этого дерева при правиле `SKILL.md` рядом.
4
+
5
+ Правило говорит приёмом и называет пути, общие для деревьев мастерской, — их переписывать
6
+ здесь не надо. Сюда идёт только то, чего пакет знать не может: как названы вещи именно в этом
7
+ репозитории, и в каком его файле каждая статья правила исполняется.
6
8
 
7
9
  Пока в файле стоит `<!-- заполняет проект -->`, правило считается неразвёрнутым: `agent-kit
8
- sync --check` отказывает, а агент читает указание, которому здесь нечего назвать.
10
+ sync --check` отказывает, а агент читает указание, у которого здесь нет адресата.
9
11
 
10
12
  ## Как это называется здесь
11
13
 
14
+ Только то, что расходится с правилом: ключ задач, адрес борды, префикс компонентов, имя
15
+ владеющей сущности, валюта хранения, набор областей коммита. Строку, которая просто повторяет
16
+ правило, сюда не переносят — она устареет отдельно от него.
17
+
12
18
  | В правиле | Здесь |
13
19
  | ----------------- | ------------------------------------------- |
14
20
  | <понятие правила> | <имя в этом коде> <!-- заполняет проект --> |
@@ -21,9 +27,9 @@ sync --check` отказывает, а агент читает указание,
21
27
 
22
28
  ## Где исполняются статьи
23
29
 
24
- Первая колонка — статья дословно, как она написана в разделе «Что здесь действует» правила
25
- (жирная часть пункта). Статья без строки и строка без статьи — расхождение: правило обещает
26
- то, чего в дереве нет, либо в дереве стоит то, о чём правило молчит.
30
+ Первая колонка — статья дословно, как она написана в разделе «Как закон применяется здесь»
31
+ (жирная часть пункта). Статья без строки и строка без статьи — расхождение: правило обещает то,
32
+ чего в дереве нет, либо в дереве стоит то, о чём правило молчит.
27
33
 
28
34
  | Статья | Где исполняется |
29
35
  | ----------------- | ------------------------------------------- |
@@ -8,7 +8,7 @@ description: Паттерн правила <имя-правила>. Брать <
8
8
  # <Что собирается>
9
9
 
10
10
  Паттерн правила `<имя-правила>`. Что при этом должно быть верно — закон
11
- `{{lawsDir}}/<закон>.md`.
11
+ `docs/constitution/<закон>.md`.
12
12
 
13
13
  ## Когда брать
14
14
 
@@ -1,41 +1,54 @@
1
1
  #!/usr/bin/env bash
2
- # Профиль этого дерева: что здесь чем зовётся и какими командами проверяется.
2
+ # Надстройка профиля дерева: команды, стенды и пары «правка документ» этого репозитория.
3
3
  #
4
- # Живёт в проекте, а не в пакете: механизм у сторожевых хуков общий, а команды, порты и пары
5
- # «правка её документ» у каждого дерева свои. Пакет везёт хуки, проект — этот файл.
4
+ # Скопировать в `.claude/rt-kit/project.sh` и дописать своё. Файл необязателен: без него
5
+ # действует умолчание пакета `.claude/rt-kit/defaults/project.sh`, где запускатель выбирается
6
+ # по локфайлу, а линтеры, форма имени ветки и образцы переизобретения уже названы.
6
7
  #
7
- # Каждая функция вправе промолчать. Молчание значит «правила на это нет», и хук пропускает:
8
- # пустой профиль оставляет хуки безвредными, а не отбивающими наугад.
8
+ # Каждая функция вправе промолчать. Молчание значит «правила на это нет», и хук пропускает.
9
+ # Объявленная здесь функция замещает умолчание ЦЕЛИКОМ — чтобы дописать, а не заменить, зовите
10
+ # из неё то же имя с суффиксом `_default`.
9
11
 
10
12
  # Где подняты приложения. Идёт в текст отказа, когда кто-то поднимает второй экземпляр.
13
+ # Умолчание молчит: чужой порт назвать хуже, чем не назвать никакого.
11
14
  RT_STANDS='<приложение> http://localhost:<порт>, <приложение> http://localhost:<порт>'
12
15
 
16
+ # Адрес боевого хранилища. Любая запись по нему отбивается совсем, и опт-аут не действует.
17
+ RT_PROD_DSN='<хост боевого хранилища>'
18
+
19
+ # Пути, у которых якорь для сквозных тестов не требуется.
20
+ RT_QA_SKIP_RE='<выражение путей>'
21
+
13
22
  # Команды, которые обязаны пройти перед пушем. По одной на строку; первая упавшая отбивает пуш.
14
23
  rt_push_checks() {
15
- cat <<'EOF'
16
- <команда линтера кода>
17
- <команда линтера стилей>
18
- <команда тестов>
19
- EOF
24
+ rt_push_checks_default
25
+ # printf '%s\n' '<своя проверка>'
20
26
  }
21
27
 
22
- # Какой документ обязан ехать тем же коммитом, что и этот файл. Печатает путь или молчит.
28
+ # Какой документ обязан ехать тем же коммитом, что и этот файл. Печатает образец пути или молчит.
23
29
  rt_docs_pair_for() {
24
30
  case "$1" in
25
- */<каталог правил>/*) printf '%s' '<зеркало правила>' ;;
26
- *.proto) printf '%s' '<спек задетого домена>' ;;
31
+ # <свой путь>) printf '%s' '<образец пути документа>' ; return 0 ;;
32
+ *) ;;
27
33
  esac
34
+
35
+ rt_docs_pair_for_default "$1"
28
36
  }
29
37
 
30
38
  # Чем линтуется этот файл сразу после правки. Печатает команду или молчит.
31
39
  rt_lint_for() {
32
- case "$1" in
33
- *.scss) printf '%s' '<команда линтера стилей> "$1"' ;;
34
- *.ts) printf '%s' '<команда линтера кода> "$1"' ;;
35
- esac
40
+ rt_lint_for_default "$1"
36
41
  }
37
42
 
38
- # Имя ветки, с которой разрешено открывать PR: номер задачи в имени. Успех — годится.
43
+ # Имя ветки, с которой разрешено открывать заявку на слияние. Успех — годится.
39
44
  rt_task_branch_ok() {
40
- printf '%s' "$1" | grep -qE '<выражение имени ветки>'
45
+ rt_task_branch_ok_default "$1"
46
+ }
47
+
48
+ # Что в этом дереве считается переизобретением. По строке «образец<таб>чем заменить».
49
+ rt_reinvented_in() {
50
+ rt_reinvented_in_default "$1"
51
+ # case "$1" in
52
+ # *.ts) printf '%s\t%s\n' '<образец>' '<чем заменить>' ;;
53
+ # esac
41
54
  }
@@ -7,7 +7,7 @@ description: Правило под закон «<Название закона>
7
7
 
8
8
  # <О чём закон> — каким приёмом
9
9
 
10
- Правило под закон `{{lawsDir}}/<закон>.md`. Закон говорит, что должно быть верно; здесь — каким
10
+ Правило под закон `docs/constitution/<закон>.md`. Закон говорит, что должно быть верно; здесь — каким
11
11
  приёмом это делается. Чем это названо в этом дереве и где лежит — `implementation.md` рядом:
12
12
  правило переносится между репозиториями, имена — нет.
13
13
 
@@ -0,0 +1,20 @@
1
+ {
2
+ "host": {
3
+ "question": "Где лежит репозиторий и очередь работ?",
4
+ "title": "хостинг репозитория",
5
+ "options": [
6
+ {
7
+ "value": "github",
8
+ "title": "GitHub — gh, issues, Projects"
9
+ },
10
+ {
11
+ "value": "gitlab",
12
+ "title": "GitLab — glab, issues, Boards"
13
+ },
14
+ {
15
+ "value": "azure",
16
+ "title": "Azure DevOps — az repos, work items, Boards"
17
+ }
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,134 @@
1
+ export const meta = {
2
+ name: 'feature',
3
+ description: 'План от PM, реализация по шагам, веер проверок QA и приёмка по исходному запросу',
4
+ whenToUse: 'Крупная правка, которая заденет несколько слоёв: контракт, хранилище, приложения, переводы',
5
+ phases: [
6
+ { title: 'План', detail: 'PM разбивает задачу на шаги с признаками готовности' },
7
+ { title: 'Реализация', detail: 'по шагу за раз — рабочее дерево одно на всех' },
8
+ { title: 'Проверка', detail: 'QA веером: тесты, сборка, браузер, состязательный разбор' },
9
+ { title: 'Приёмка', detail: 'PM сверяет сделанное с исходным запросом' },
10
+ ],
11
+ };
12
+
13
+ // Задача приходит строкой в args; без неё сценарий бессмыслен.
14
+ const task = typeof args === 'string' ? args : (args?.task ?? '');
15
+ if (!task) {
16
+ throw new Error('Нужна задача: передай её строкой в args');
17
+ }
18
+
19
+ const PLAN = {
20
+ type: 'object',
21
+ additionalProperties: false,
22
+ required: ['steps', 'risks', 'acceptance'],
23
+ properties: {
24
+ steps: {
25
+ type: 'array',
26
+ maxItems: 6,
27
+ items: {
28
+ type: 'object',
29
+ additionalProperties: false,
30
+ required: ['title', 'scope', 'done'],
31
+ properties: {
32
+ title: { type: 'string' },
33
+ scope: { type: 'string', description: 'что входит и что НЕ входит' },
34
+ done: { type: 'string', description: 'проверяемый признак готовности' },
35
+ },
36
+ },
37
+ },
38
+ risks: { type: 'array', items: { type: 'string' } },
39
+ acceptance: { type: 'array', items: { type: 'string' }, description: 'критерии приёмки по исходному запросу' },
40
+ },
41
+ };
42
+
43
+ const FINDINGS = {
44
+ type: 'object',
45
+ additionalProperties: false,
46
+ required: ['findings', 'checked'],
47
+ properties: {
48
+ findings: {
49
+ type: 'array',
50
+ items: {
51
+ type: 'object',
52
+ additionalProperties: false,
53
+ required: ['what', 'where', 'evidence', 'severity'],
54
+ properties: {
55
+ what: { type: 'string' },
56
+ where: { type: 'string' },
57
+ evidence: { type: 'string', description: 'вывод команды или замер, а не пересказ' },
58
+ severity: { type: 'string', enum: ['blocker', 'major', 'minor'] },
59
+ preExisting: { type: 'boolean' },
60
+ },
61
+ },
62
+ },
63
+ checked: { type: 'array', items: { type: 'string' } },
64
+ },
65
+ };
66
+
67
+ phase('План');
68
+ const plan = await agent(
69
+ `Задача от пользователя:\n\n${task}\n\nРазбери её и верни план. Шагов не больше шести; ` +
70
+ `каждый — самостоятельная правка с проверяемым признаком готовности.`,
71
+ { agentType: 'project-manager', label: 'план', schema: PLAN }
72
+ );
73
+ log(`План: ${plan.steps.length} шаг(ов), рисков ${plan.risks.length}`);
74
+
75
+ // Шаги идут по очереди, а не веером: рабочее дерево одно, и параллельные
76
+ // правки одних и тех же файлов затирали бы друг друга.
77
+ phase('Реализация');
78
+ const done = [];
79
+ for (const [index, step] of plan.steps.entries()) {
80
+ const result = await agent(
81
+ `Задача целиком: ${task}\n\nТвой шаг ${index + 1} из ${plan.steps.length}: ${step.title}\n` +
82
+ `Границы: ${step.scope}\nПризнак готовности: ${step.done}\n\n` +
83
+ `Уже сделано на предыдущих шагах:\n${done.join('\n') || '— ничего'}\n\n` +
84
+ `Соблюдай правила дерева из CLAUDE.md и .claude/skills. Перед правкой файла загрузи ` +
85
+ `подходящее правило через инструмент Skill — иначе гейт правил заблокирует правку. ` +
86
+ `Никаких git-команд. Верни коротко: какие файлы изменил и чем подтверждается признак готовности.`,
87
+ { label: `шаг ${index + 1}: ${step.title}`, phase: 'Реализация' }
88
+ );
89
+ done.push(`${step.title}: ${result ?? 'шаг не выполнен'}`);
90
+ }
91
+
92
+ // Здесь барьер оправдан: приёмке нужны все находки разом, а измерения
93
+ // независимы и честно параллелятся.
94
+ phase('Проверка');
95
+ const LENSES = [
96
+ { key: 'тесты', prompt: 'Прогони юнит-тесты и e2e по затронутому. Отдели новые падения от доэтапных.' },
97
+ { key: 'сборка', prompt: 'Прогони сборки затронутых приложений и линтеры. Доэтапные ошибки помечай как доэтапные.' },
98
+ {
99
+ key: 'браузер',
100
+ prompt: 'Проверь результат в браузере замерами: вычисленные стили, геометрия, контраст. Серверы разработки уже подняты — свой не поднимай.',
101
+ },
102
+ {
103
+ key: 'разбор',
104
+ prompt: 'Состязательно разбери правку: граничные значения, вторая локаль, тёмная тема, узкий экран, отвалившийся сервер, отдача страницы сервером.',
105
+ },
106
+ ];
107
+ const reports = (
108
+ await parallel(
109
+ LENSES.map(
110
+ (lens) => () =>
111
+ agent(`Задача, которую выполняли: ${task}\n\nЧто сделано:\n${done.join('\n')}\n\n${lens.prompt}`, {
112
+ agentType: 'qa-engineer',
113
+ label: `qa: ${lens.key}`,
114
+ phase: 'Проверка',
115
+ schema: FINDINGS,
116
+ })
117
+ )
118
+ )
119
+ ).filter(Boolean);
120
+
121
+ const findings = reports.flatMap((report) => report.findings);
122
+ const blockers = findings.filter((finding) => finding.severity === 'blocker' && !finding.preExisting);
123
+ log(`Находок ${findings.length}, из них блокеров ${blockers.length}`);
124
+
125
+ phase('Приёмка');
126
+ const verdict = await agent(
127
+ `Исходный запрос пользователя:\n\n${task}\n\nКритерии приёмки:\n${plan.acceptance.join('\n')}\n\n` +
128
+ `Что сделано:\n${done.join('\n')}\n\nНаходки проверяющих:\n${JSON.stringify(findings, null, 1)}\n\n` +
129
+ `Вынеси вердикт: что принято, что нет и почему. Отдельно назови, что из исходного запроса ` +
130
+ `осталось незакрытым или тихо сузилось.`,
131
+ { agentType: 'project-manager', label: 'приёмка', phase: 'Приёмка' }
132
+ );
133
+
134
+ return { plan, done, findings, blockers, verdict };
@@ -0,0 +1,150 @@
1
+ export const meta = {
2
+ name: 'plan',
3
+ description: 'После разбора с владельцем: нужна ли работа, договорённость о продукте, её состязательный разбор и замысел реализации',
4
+ whenToUse: 'Разбор просьбы владельца закрыт, папка задачи заведена, код ещё не пишется',
5
+ phases: [
6
+ { title: 'Нужность', detail: 'что даёт работа и что из неё выкидывается' },
7
+ { title: 'Договорённость', detail: 'спек фичи в proposed/ по разбору' },
8
+ { title: 'Критика', detail: 'что в договорённости недосказано' },
9
+ { title: 'Замысел', detail: 'этапы с признаками готовности и разбивка на задачи' },
10
+ ],
11
+ };
12
+
13
+ // Папка задачи приходит в args; без неё конвейеру нечего читать. Разбор просьбы владельца
14
+ // лежит в ней и остаётся единственным источником: пересказывать его в промпте значит терять
15
+ // слова владельца, ради которых он и записан.
16
+ const dir = typeof args === 'string' ? args : (args?.dir ?? '');
17
+ if (!dir) {
18
+ throw new Error('Нужна папка задачи: передай её строкой в args, например docs/tasks/<ветка>');
19
+ }
20
+
21
+ const grill = `${dir}/grill.md`;
22
+
23
+ const WORTH = {
24
+ type: 'object',
25
+ additionalProperties: false,
26
+ required: ['verdict', 'gives', 'drop'],
27
+ properties: {
28
+ verdict: { type: 'string', enum: ['делать', 'делать урезанно', 'отложить'] },
29
+ gives: { type: 'string', description: 'что владелец получит' },
30
+ drop: { type: 'array', items: { type: 'string' }, description: 'что выкидывается без потери цели' },
31
+ risks: { type: 'array', items: { type: 'string' } },
32
+ },
33
+ };
34
+
35
+ const DRAFT = {
36
+ type: 'object',
37
+ additionalProperties: false,
38
+ required: ['path', 'rules', 'gaps'],
39
+ properties: {
40
+ path: { type: 'string', description: 'заведённая директория в docs/specs/*/proposed/' },
41
+ rules: { type: 'array', items: { type: 'string' }, description: 'правила по одной строке' },
42
+ gaps: { type: 'array', items: { type: 'string' }, description: 'пробелы, которые не закрыть без владельца' },
43
+ },
44
+ };
45
+
46
+ const FINDINGS = {
47
+ type: 'object',
48
+ additionalProperties: false,
49
+ required: ['findings'],
50
+ properties: {
51
+ findings: {
52
+ type: 'array',
53
+ items: {
54
+ type: 'object',
55
+ additionalProperties: false,
56
+ required: ['what', 'where', 'cost'],
57
+ properties: {
58
+ what: { type: 'string', description: 'что недосказано' },
59
+ where: { type: 'string', description: 'файл и правило дословно' },
60
+ cost: { type: 'string', description: 'чем обернётся в коде' },
61
+ },
62
+ },
63
+ },
64
+ },
65
+ };
66
+
67
+ const PLAN = {
68
+ type: 'object',
69
+ additionalProperties: false,
70
+ required: ['tasks', 'steps', 'acceptance'],
71
+ properties: {
72
+ tasks: {
73
+ type: 'array',
74
+ description: 'на сколько задач делится работа; одна — обычный случай',
75
+ items: {
76
+ type: 'object',
77
+ additionalProperties: false,
78
+ required: ['title', 'slug', 'why'],
79
+ properties: {
80
+ title: { type: 'string' },
81
+ slug: { type: 'string' },
82
+ why: { type: 'string', description: 'почему это откатывается отдельно' },
83
+ },
84
+ },
85
+ },
86
+ steps: {
87
+ type: 'array',
88
+ maxItems: 8,
89
+ items: {
90
+ type: 'object',
91
+ additionalProperties: false,
92
+ required: ['title', 'scope', 'done'],
93
+ properties: {
94
+ title: { type: 'string' },
95
+ scope: { type: 'string', description: 'что входит и что НЕ входит' },
96
+ done: { type: 'string', description: 'проверяемый признак готовности' },
97
+ },
98
+ },
99
+ },
100
+ acceptance: { type: 'array', items: { type: 'string' } },
101
+ },
102
+ };
103
+
104
+ phase('Нужность');
105
+ const worth = await agent(
106
+ `Разбор просьбы владельца — \`${grill}\`. Прочитай его целиком.\n\n` +
107
+ `Скажи, что эта работа даёт владельцу, что из неё выкидывается без потери цели и почему её ` +
108
+ `стоит делать сейчас, а не через полгода. Отвергнутое называй с причиной.`,
109
+ { agentType: 'business-analyst', label: 'нужность', schema: WORTH }
110
+ );
111
+ log(`Нужность: ${worth.verdict}; выкидывается пунктов ${worth.drop.length}`);
112
+
113
+ if (worth.verdict === 'отложить') {
114
+ log('Работа не начинается: решение относится владельцу.');
115
+ return { worth, stopped: 'аналитик предложил отложить — решение за владельцем' };
116
+ }
117
+
118
+ phase('Договорённость');
119
+ const draft = await agent(
120
+ `Разбор просьбы владельца — \`${grill}\`. Прочитай его целиком и напиши по нему договорённость ` +
121
+ `о продукте: \`docs/specs/<домен>/proposed/<фича>/\`.\n\n` +
122
+ `Из работы выкинуто: ${worth.drop.join('; ') || '— ничего'}.\n\n` +
123
+ `Пробелы, которые не закрываются разбором, не додумывай — верни их списком.`,
124
+ { agentType: 'spec-writer', label: 'договорённость', schema: DRAFT }
125
+ );
126
+ log(`Договорённость: ${draft.path}, правил ${draft.rules.length}, пробелов ${draft.gaps.length}`);
127
+
128
+ phase('Критика');
129
+ const critique = await agent(
130
+ `Договорённость — \`${draft.path}\`, разбор просьбы владельца — \`${grill}\`.\n\n` +
131
+ `Состязательно разбери договорённость: что недосказано, где два прочтения, какие случаи ` +
132
+ `не названы. Ничего не правь.`,
133
+ { agentType: 'spec-critic', label: 'критика', schema: FINDINGS }
134
+ );
135
+ log(`Критика: находок ${critique.findings.length}`);
136
+
137
+ phase('Замысел');
138
+ const plan = await agent(
139
+ `Разбор просьбы владельца — \`${grill}\`, договорённость — \`${draft.path}\`.\n\n` +
140
+ `Находки состязательного разбора:\n${critique.findings.map((f) => `- ${f.what} (${f.where})`).join('\n') || '— нет'}\n\n` +
141
+ `Собери замысел реализации: этапы с границами и проверяемым признаком готовности у каждого. ` +
142
+ `Отдельно скажи, на сколько задач делится работа: делится то, что придётся откатывать порознь, ` +
143
+ `а не то, что просто объёмно. Одна задача — обычный случай.`,
144
+ { agentType: 'project-manager', label: 'замысел', schema: PLAN }
145
+ );
146
+ log(`Замысел: задач ${plan.tasks.length}, этапов ${plan.steps.length}`);
147
+
148
+ // Ничего не записывается на диск отсюда: замысел и пробелы уходят владельцу, а `plan.md`
149
+ // пишет главный агент — вопросы к владельцу задаёт только он.
150
+ return { worth, draft, critique: critique.findings, plan };
@@ -1 +1 @@
1
- {"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAaA,OAAO,EAA8B,iBAAiB,EAAc,MAAM,oBAAoB,CAAC;AAwF/F,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsB9E"}
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"}