@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
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env bash
2
+ # Профиль дерева: чем здесь проверяется правка и что считается переизобретением.
3
+ #
4
+ # Умолчание пакета. Всё, что общего у деревьев этой мастерской, живёт здесь: запускатель Nx,
5
+ # линтер кода, линтер стилей, набор образцов переизобретения. Своё дерево дописывает
6
+ # надстройкой — `.claude/rt-kit/project.sh`: она грузится второй, объявляет ту же функцию
7
+ # заново и вправе позвать отсюда её же с суффиксом `_default`.
8
+ #
9
+ # Каждая функция вправе промолчать. Молчание значит «правила на это нет», и хук пропускает.
10
+
11
+ # Запускатель пакетов — по локфайлу, а не по договорённости: деревья с pnpm и с npm лежат в
12
+ # одной мастерской, и зашитый здесь `npm` в первом же из них печатал бы команду, которой нет.
13
+ rt_runner() {
14
+ root="${CLAUDE_PROJECT_DIR:-.}"
15
+ if [ -f "$root/pnpm-lock.yaml" ]; then
16
+ printf '%s' 'pnpm exec'
17
+ elif [ -f "$root/yarn.lock" ]; then
18
+ printf '%s' 'yarn'
19
+ else
20
+ printf '%s' 'npx'
21
+ fi
22
+ }
23
+
24
+ # Где подняты приложения. Идёт в текст отказа, когда кто-то поднимает второй экземпляр.
25
+ # Порты у каждого дерева свои, поэтому умолчание молчит: назвать чужой порт хуже, чем не назвать.
26
+ RT_STANDS="${RT_STANDS:-}"
27
+
28
+ # Команды, которые обязаны пройти перед пушем. По одной на строку; первая упавшая отбивает пуш.
29
+ # Линтер стилей отдельной строкой: линтер кода файлы стилей не читает вовсе.
30
+ #
31
+ # Первый параметр — база: ветка, относительно которой считается вклад. Пустая означает, что
32
+ # удалённого нет, и тогда гоняется всё: набор строже нужного безопасен, набор уже нужного — нет.
33
+ rt_push_checks_default() {
34
+ runner="$(rt_runner)"
35
+ if [ -n "$1" ]; then
36
+ printf '%s\n' "$runner nx affected -t lint test --base=$1"
37
+ else
38
+ printf '%s\n' "$runner nx run-many -t lint test --all"
39
+ fi
40
+ [ -f "${CLAUDE_PROJECT_DIR:-.}/stylelint.config.js" ] && printf '%s\n' "$runner stylelint \"**/*.scss\" --max-warnings 0"
41
+
42
+ return 0
43
+ }
44
+
45
+ # Какой документ обязан ехать тем же коммитом, что и этот файл. Печатает образец пути или молчит.
46
+ rt_docs_pair_for_default() {
47
+ case "$1" in
48
+ # Тест — не описание кода: он его проверяет.
49
+ *.spec.ts) return 0 ;;
50
+ # Контракт правится вместе со спеком домена: разошедшись, они врут оба.
51
+ *.proto) printf '%s' 'docs/specs/.*/spec\.md' ;;
52
+ # Правило и его спутник здесь не называются: их пару держит сам гард, и держит точнее —
53
+ # он сверяет раздел с утверждениями, а не факт правки файла.
54
+ # Хук и набор его сценариев: гард разбирает текст команд, и уточнение шаблона обычно
55
+ # смещает границу, а не сужает.
56
+ .claude/hooks/*.sh) printf '%s' '.claude/hooks/tests/.*' ;;
57
+ esac
58
+ }
59
+
60
+ # Чем линтуется этот файл сразу после правки. Печатает команду или молчит.
61
+ #
62
+ # Путь подставляется здесь, а не оставляется позиционным параметром: хук исполняет напечатанное
63
+ # вычислением строки, и `$1` в нём разрешился бы в параметр самого хука, то есть в пустоту.
64
+ rt_lint_for_default() {
65
+ runner="$(rt_runner)"
66
+ case "$1" in
67
+ *.scss) printf '%s stylelint --max-warnings 0 "%s"' "$runner" "$1" ;;
68
+ *.ts | *.html) printf '%s eslint "%s"' "$runner" "$1" ;;
69
+ esac
70
+ }
71
+
72
+ # Каталог папок задач. Пусто — ведения работы папкой в дереве нет, и гард замысла молчит.
73
+ RT_TASKS_DIR="${RT_TASKS_DIR:-docs/tasks}"
74
+
75
+ # Код приложения ли это. Успех — да, и тогда правка требует замысла на диске.
76
+ #
77
+ # Признак — путь, а не оценка на глаз: оценку назначает тот, кому она мешает, и порог плывёт.
78
+ # Правила, тексты, обвязка и зависимости под требование не попадают — иначе разбор задачи
79
+ # нельзя было бы вести до заведения ветки.
80
+ rt_is_app_code_default() {
81
+ case "$1" in
82
+ */apps/* | */libs/* | */projects/*) return 0 ;;
83
+ *) return 1 ;;
84
+ esac
85
+ }
86
+
87
+ # Имя ветки, с которой разрешено открывать заявку на слияние: в имени стоит номер задачи.
88
+ # Приставка — либо род правки, либо метка очереди работ: обе формы носят номер, а он и нужен.
89
+ #
90
+ # Хвост после номера — строчными и через дефис. Имя ветки читают глазами в списке и набирают
91
+ # руками, а регистр в нём различает две ветки, отличающиеся только им, — и та, что нужна, при
92
+ # переключении находится не с первого раза.
93
+ rt_task_branch_ok_default() {
94
+ printf '%s' "$1" \
95
+ | grep -qE '^([A-Z]+-)?[0-9]+-[a-z0-9][a-z0-9-]*$|^(feat|fix|refactor|docs|chore|style|perf|test|build|ci)/[0-9]+-[a-z0-9][a-z0-9-]*$'
96
+ }
97
+
98
+ # Адрес боевого хранилища: образец, по которому его узнают в командной строке — порт туннеля,
99
+ # хост, домен. Любая запись по нему отбивается совсем, и опт-аут не действует. Умолчание
100
+ # молчит: чужой адрес здесь опаснее неназванного — он отбивал бы работу с локальной базой.
101
+ RT_PROD_DSN="${RT_PROD_DSN:-}"
102
+
103
+ # Подключения среды разработки в лицо: по одному тексту запроса бой от локальной копии не
104
+ # отличить, база выбирается идентификатором подключения. Идентификаторы локальны для машины.
105
+ RT_PROD_CONNECTIONS="${RT_PROD_CONNECTIONS:-}"
106
+ RT_LOCAL_CONNECTIONS="${RT_LOCAL_CONNECTIONS:-}"
107
+
108
+ # Порты одноразовых баз: по ним вопрос не задаётся. Не назван — исключения нет вовсе.
109
+ RT_SCRATCH_PORT_RE="${RT_SCRATCH_PORT_RE:-}"
110
+
111
+ # Форма номера в заголовке заявки на слияние. Тот же номер стоит у задачи и у ветки.
112
+ RT_TASK_TITLE_RE="${RT_TASK_TITLE_RE:-^\[[A-Za-z]+-[0-9]+\][[:space:]]+[^[:space:]]}"
113
+
114
+ # Чем заводится задача и чем сверяется очередь работ. Идут в текст отказа гарда поставки:
115
+ # отказ без действия обходят, а не исполняют.
116
+ RT_TASK_NEW_CMD="${RT_TASK_NEW_CMD:-npm run task:new}"
117
+ RT_BOARD_CHECK_CMD="${RT_BOARD_CHECK_CMD:-npm run check:board}"
118
+
119
+ # Учётная запись, которую ставят исполнителем. Умолчание молчит: у каждого дерева она своя.
120
+ RT_TASK_BOT="${RT_TASK_BOT:-}"
121
+
122
+ # Состояние задачи одним объектом: exists, open, onBoard, assigned, numbered. Спрашивает
123
+ # помощника очереди работ — того же, которым пользуются сверка и команда заведения, чтобы
124
+ # гард и очередь одинаково понимали «задача в порядке». Нет узла, нет помощника, нет сети —
125
+ # молчание, и ярус состояния пропускается: проверять нечем.
126
+ rt_task_state_default() {
127
+ command -v node >/dev/null 2>&1 || return 1
128
+ [ -f "${RT_BOARD_HELPER:-tools/board.mjs}" ] || return 1
129
+ state="$(node "${RT_BOARD_HELPER:-tools/board.mjs}" task "$1" 2>/dev/null)" || return 1
130
+ [ -z "$state" ] && return 1
131
+ # Ответ с меткой «сети не было» состоянием не является: по нему нельзя отличить задачу,
132
+ # которой нет, от задачи, о которой не спросили.
133
+ printf '%s' "$state" | jq -e 'has("offline") | not' >/dev/null 2>&1 || return 1
134
+ printf '%s' "$state"
135
+ }
136
+
137
+ # Что в этом дереве считается переизобретением. По строке «образец<таб>чем заменить».
138
+ # Образцы узкие намеренно: гард сверяет только НОВЫЙ текст, и широкий образец отбивал бы
139
+ # правку, которая ничего нового не заводит.
140
+ rt_reinvented_in_default() {
141
+ case "$1" in
142
+ *.ts)
143
+ printf '%s\t%s\n' '@(Input|Output|ViewChild|ViewChildren|ContentChild)\(' 'input(), output(), viewChild(), contentChild() — реактивный вход и выход'
144
+ printf '%s\t%s\n' 'get [a-zA-Z]+\(\)[[:space:]]*(:|\{)' 'computed(): производное значение сигналом, а не геттером'
145
+ ;;
146
+ *.html)
147
+ printf '%s\t%s\n' '\[ngClass\]|\[class\.' 'директивы класса кита'
148
+ ;;
149
+ *.scss)
150
+ printf '%s\t%s\n' '#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?\b' 'токен оформления вместо записанного цвета'
151
+ ;;
152
+ esac
153
+ }
154
+
155
+ # Где якорь для спек не требуется. Витрина, корневая разметка и сборка — общее у всех деревьев;
156
+ # своё дерево дописывает надстройкой.
157
+ RT_QA_SKIP_RE="${RT_QA_SKIP_RE:-/node_modules/|/dist/|\.stories\.html\$|/src/index\.html\$}"
158
+
159
+ # По какому имени тег опознаётся компонентом этого дерева. Умолчание — составной тег: имя с
160
+ # дефисом принадлежит компоненту, а не разметке, и это верно везде, где есть свои компоненты.
161
+ RT_QA_COMPONENT_RE="${RT_QA_COMPONENT_RE:--}"
162
+
163
+ # Теги, которые спека не нажимает: оформление, разметка страницы, индикаторы. Перечисляются
164
+ # именами через пробел. Умолчание молчит: у каждого кита свои, а чужое имя здесь глушило бы
165
+ # проверку на теге, которого в этом дереве нет.
166
+ rt_qa_decorative_default() {
167
+ return 0
168
+ }
169
+
170
+ # Умолчания под общими именами. Надстройка проекта объявит любое из них заново — и позовёт
171
+ # отсюда то же имя с суффиксом `_default` для всего, чего не назвала сама.
172
+ rt_push_checks() { rt_push_checks_default "$@"; }
173
+ rt_docs_pair_for() { rt_docs_pair_for_default "$@"; }
174
+ rt_lint_for() { rt_lint_for_default "$@"; }
175
+ rt_task_branch_ok() { rt_task_branch_ok_default "$@"; }
176
+ rt_reinvented_in() { rt_reinvented_in_default "$@"; }
177
+ rt_is_app_code() { rt_is_app_code_default "$@"; }
178
+ rt_qa_decorative() { rt_qa_decorative_default "$@"; }
179
+ rt_task_state() { rt_task_state_default "$@"; }
File without changes
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse mcp__claude-in-chrome__select_browser
2
3
  # Гард выбора браузера. PreToolUse на выборе браузера расширением.
3
4
  #
4
5
  # Отклоняет любой профиль, кроме закреплённого: чужой стоит лишнего круга и приводит в браузер,
@@ -11,7 +12,7 @@
11
12
 
12
13
  input="$(cat 2>/dev/null)"
13
14
 
14
- device_id="$("${CLAUDE_PROJECT_DIR:-.}/{{hooksDir}}/browser-device-id.sh" 2>/dev/null)"
15
+ device_id="$("${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/browser-device-id.sh" 2>/dev/null)"
15
16
  [ -z "$device_id" ] && exit 0
16
17
 
17
18
  requested="$(printf '%s' "$input" | jq -r '.tool_input.deviceId // empty' 2>/dev/null)"
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse AskUserQuestion
3
+ # PreToolUse guard for AskUserQuestion.
4
+ #
5
+ # The browser choice is already made and pinned in browser-device-id.sh — asking again is noise, and the
6
+ # answer could only ever be the pinned profile. Only questions actually about PICKING a browser
7
+ # are blocked; every other question passes untouched.
8
+ #
9
+ # A bare "browser"/"браузер" substring is too broad for a web-dev project: questions about
10
+ # client-side code, user agents, cross-browser bugs etc. legitimately use the word without
11
+ # being about which Chrome profile to automate. Anchor on selection phrasing instead
12
+ # (deviceId, "which/what browser", "какой браузер").
13
+ #
14
+ # FAIL-OPEN when browser-device-id.sh prints nothing.
15
+
16
+ input="$(cat 2>/dev/null)"
17
+
18
+ device_id="$("${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/browser-device-id.sh" 2>/dev/null)"
19
+ [ -z "$device_id" ] && exit 0
20
+
21
+ questions="$(printf '%s' "$input" | jq -r '[.tool_input.questions[]? | .question, .header, (.options[]?.label)] | join(" ")' 2>/dev/null)"
22
+ [ -z "$questions" ] && exit 0
23
+
24
+ printf '%s' "$questions" | grep -qiE 'deviceid|device id|(which|what|pick|choose|select)[^.]{0,25}\bbrowser\b|\bbrowser\b[^.]{0,25}(profile|to use)|как(ой|ую)?[^.]{0,15}браузер|брауз[а-я]*[^.]{0,20}(использовать|выбрать|выбор|нужен|запустить)' || exit 0
25
+
26
+ echo "Do not ask which browser to use — the profile is pinned. Call select_browser with deviceId ${device_id} ('Main' profile)." >&2
27
+ exit 2
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse mcp__claude-in-chrome__(list_connected_browsers|switch_browser)
2
3
  # Гард перечисления и переключения браузеров. PreToolUse.
3
4
  #
4
5
  # Сессии проекта живут в одном закреплённом профиле. Перечисление и переключение отдают общие
@@ -10,7 +11,7 @@
10
11
 
11
12
  cat >/dev/null 2>&1
12
13
 
13
- device_id="$("${CLAUDE_PROJECT_DIR:-.}/{{hooksDir}}/browser-device-id.sh" 2>/dev/null)"
14
+ device_id="$("${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/browser-device-id.sh" 2>/dev/null)"
14
15
  [ -z "$device_id" ] && exit 0
15
16
 
16
17
  echo "Не перечисляй и не переключай браузеры. Вызови выбор браузера с профилем ${device_id} — единственным, где сделан вход." >&2
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse mcp__playwright__.*|mcp__chrome-devtools__.*|Bash
2
3
  # Гард обходных путей к браузеру. PreToolUse.
3
4
  #
4
5
  # Закрепление профиля чего-то стоит только тогда, когда дверь одна. Здесь перечислены двери,
@@ -13,7 +14,7 @@
13
14
 
14
15
  input="$(cat 2>/dev/null)"
15
16
 
16
- device_id="$("${CLAUDE_PROJECT_DIR:-.}/{{hooksDir}}/browser-device-id.sh" 2>/dev/null)"
17
+ device_id="$("${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/browser-device-id.sh" 2>/dev/null)"
17
18
  [ -z "$device_id" ] && exit 0
18
19
 
19
20
  tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse mcp__claude-in-chrome__.*
2
3
  # Гард свежести выбора браузера. PreToolUse на всех остальных вызовах расширения.
3
4
  #
4
5
  # ЗАЧЕМ ОН ЕСТЬ — отказ, из которого он вырос: расширение действует на тот браузер, который
@@ -20,7 +21,7 @@
20
21
 
21
22
  input="$(cat 2>/dev/null)"
22
23
 
23
- device_id="$("${CLAUDE_PROJECT_DIR:-.}/{{hooksDir}}/browser-device-id.sh" 2>/dev/null)"
24
+ device_id="$("${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/browser-device-id.sh" 2>/dev/null)"
24
25
  [ -z "$device_id" ] && exit 0
25
26
 
26
27
  tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
@@ -4,7 +4,7 @@
4
4
  # Версионируемый шаблон: рабочая копия хуков гита не версионируется, поэтому файл ставится в
5
5
  # неё отдельно — скриптом подготовки при установке зависимостей. Переустановка руками, если
6
6
  # подготовка почему-то не отработала:
7
- # cp {{hooksDir}}/commit-msg.sh .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
7
+ # cp .claude/hooks/commit-msg.sh .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
8
8
  #
9
9
  # Намеренно НЕ через обёртку, подменяющую путь хуков: подмена уводит гит в свой каталог и рвёт
10
10
  # остальные хуки, уже лежащие в рабочей копии. Родной путь оставляет их нетронутыми.
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: SessionStart startup|resume|compact|clear
2
3
  # Вход в слой законов. SessionStart.
3
4
  #
4
5
  # Файл закона сам по себе не приносит в контекст ничего — его читают, только когда за ним
@@ -11,7 +12,7 @@
11
12
  # ОТКАЗ В ПОЛЬЗУ РАБОТЫ: любая ошибка начинает сессию без добавленного контекста (exit 0).
12
13
  # Сломанный вход не имеет права остановить сессию.
13
14
 
14
- dir="${CLAUDE_PROJECT_DIR:-.}/{{lawsDir}}"
15
+ dir="${CLAUDE_PROJECT_DIR:-.}/docs/constitution"
15
16
  [ -d "$dir" ] || exit 0
16
17
 
17
18
  index=""
@@ -19,15 +20,15 @@ for law in "$dir"/*.md; do
19
20
  [ -f "$law" ] || continue
20
21
  title="$(grep -m1 '^# ' "$law" 2>/dev/null | sed 's/^# //')"
21
22
  [ -z "$title" ] && continue
22
- index="${index} {{lawsDir}}/$(basename "$law") — ${title}"$'\n'
23
+ index="${index} docs/constitution/$(basename "$law") — ${title}"$'\n'
23
24
  done
24
25
  [ -z "$index" ] && exit 0
25
26
 
26
27
  read -r -d '' context <<EOF
27
- ЗАКОНЫ ПРОЕКТА (слой @rt-tools/agent-kit, разложен в {{lawsDir}}/).
28
+ ЗАКОНЫ ПРОЕКТА (слой @rt-tools/agent-kit, разложен в docs/constitution/).
28
29
 
29
30
  Закон говорит, ЧТО должно быть верно, и не знает ни путей, ни имён файлов. Правило — каким
30
- приёмом это делается — живёт в {{rulesDir}}/, а имена этого дерева при нём — в
31
+ приёмом это делается — живёт в .claude/skills/, а имена этого дерева при нём — в
31
32
  implementation.md рядом. Закон не отменяет правила и не заменяется им: перед решением, которое
32
33
  закон задевает, читается закон целиком, правило — как обычно.
33
34
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # rt-hook: PreToolUse Bash|mcp__webstorm__execute_terminal_command|mcp__webstorm__execute_run_configuration|mcp__webstorm__execute_tool
2
3
  # Гард второго сервера разработки. PreToolUse.
3
4
  #
4
5
  # Приложения уже подняты владельцем, и всякая проверка через браузер идёт туда. Второй
@@ -9,7 +10,7 @@
9
10
  # Отбивается всё, что ПОДНИМАЕТ сервер. Сборка, тесты, линтеры, запросы к поднятым портам и
10
11
  # осмотр слушателей проходят.
11
12
  #
12
- # Где именно подняты приложения, знает профиль проекта: {{projectProfile}}, переменная
13
+ # Где именно подняты приложения, знает профиль проекта: .claude/rt-kit/project.sh, переменная
13
14
  # RT_STANDS. Нет профиля — текст отказа остаётся общим, сам гард работает.
14
15
 
15
16
  input="$(cat 2>/dev/null)"
@@ -66,12 +67,13 @@ case "$cmd" in
66
67
  printf '%s' "$cmd" | grep -qE '(^|[[:space:]])git[[:space:]]+daemon([[:space:]]|$)' || exit 0 ;;
67
68
  esac
68
69
 
69
- stands=""
70
- profile="${CLAUDE_PROJECT_DIR:-.}/{{projectProfile}}"
71
- if [ -f "$profile" ]; then
70
+ # Профиль дерева: сперва умолчание пакета, поверх него — надстройка проекта, если она есть.
71
+ rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
72
+ for profile in "$rt_hooks_dir/../rt-kit/defaults/project.sh" "$rt_hooks_dir/../defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/project.sh"; do
72
73
  # shellcheck disable=SC1090
73
- . "$profile" 2>/dev/null && stands="${RT_STANDS:-}"
74
- fi
74
+ [ -f "$profile" ] && . "$profile" 2>/dev/null
75
+ done
76
+ stands="${RT_STANDS:-}"
75
77
 
76
78
  deny() {
77
79
  if [ -n "$stands" ]; then