@nitra/cursor 1.9.21 → 1.10.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 (200) hide show
  1. package/.claude-template/hooks/capture-decisions.sh +3 -3
  2. package/.claude-template/hooks/normalize-decisions.sh +370 -0
  3. package/CHANGELOG.md +43 -0
  4. package/bin/n-cursor.js +56 -49
  5. package/package.json +10 -5
  6. package/rules/abie/auto.md +1 -0
  7. package/{scripts/check-abie.mjs → rules/abie/js/check.mjs} +5 -5
  8. package/rules/adr/adr.mdc +150 -0
  9. package/{scripts/check-adr.mjs → rules/adr/js/check.mjs} +85 -41
  10. package/rules/adr/policy/settings_json/settings_json.rego +37 -0
  11. package/rules/adr/policy/settings_local_json/settings_local_json.rego +40 -0
  12. package/rules/bun/auto.md +1 -0
  13. package/{scripts/check-bun.mjs → rules/bun/js/check.mjs} +1 -1
  14. package/rules/capacitor/auto.md +1 -0
  15. package/{scripts/check-capacitor.mjs → rules/capacitor/js/check.mjs} +1 -1
  16. package/rules/changelog/auto.md +1 -0
  17. package/{scripts/check-changelog.mjs → rules/changelog/js/check.mjs} +2 -2
  18. package/rules/docker/auto.md +1 -0
  19. package/{scripts/check-docker.mjs → rules/docker/js/check.mjs} +5 -5
  20. package/{scripts/run-docker.mjs → rules/docker/js/run.mjs} +5 -5
  21. package/rules/ga/auto.md +1 -0
  22. package/{scripts/check-ga.mjs → rules/ga/js/check.mjs} +4 -4
  23. package/{scripts/lint-ga.mjs → rules/ga/js/lint.mjs} +2 -2
  24. package/rules/graphql/auto.md +1 -0
  25. package/{scripts/check-graphql.mjs → rules/graphql/js/check.mjs} +5 -5
  26. package/rules/hasura/auto.md +1 -0
  27. package/{scripts/check-hasura.mjs → rules/hasura/js/check.mjs} +4 -4
  28. package/rules/image-avif/auto.md +1 -0
  29. package/{scripts/check-image-avif.mjs → rules/image-avif/js/check.mjs} +5 -5
  30. package/rules/image-compress/auto.md +1 -0
  31. package/{scripts/check-image-compress.mjs → rules/image-compress/js/check.mjs} +1 -1
  32. package/rules/js-bun-db/auto.md +1 -0
  33. package/{scripts/check-js-bun-db.mjs → rules/js-bun-db/js/check.mjs} +5 -5
  34. package/rules/js-bun-redis/auto.md +1 -0
  35. package/{scripts/check-js-bun-redis.mjs → rules/js-bun-redis/js/check.mjs} +4 -4
  36. package/rules/js-lint/auto.md +1 -0
  37. package/{scripts/check-js-lint.mjs → rules/js-lint/js/check.mjs} +1 -1
  38. package/rules/js-mssql/auto.md +1 -0
  39. package/{scripts/check-js-mssql.mjs → rules/js-mssql/js/check.mjs} +5 -5
  40. package/rules/js-run/auto.md +1 -0
  41. package/{scripts/check-js-run.mjs → rules/js-run/js/check.mjs} +11 -11
  42. package/rules/k8s/auto.md +1 -0
  43. package/{scripts/check-k8s.mjs → rules/k8s/js/check.mjs} +4 -4
  44. package/{scripts/run-k8s.mjs → rules/k8s/js/run.mjs} +4 -4
  45. package/rules/nginx-default-tpl/auto.md +1 -0
  46. package/{scripts/check-nginx-default-tpl.mjs → rules/nginx-default-tpl/js/check.mjs} +7 -7
  47. package/rules/npm-module/auto.md +1 -0
  48. package/{scripts/check-npm-module.mjs → rules/npm-module/js/check.mjs} +4 -4
  49. package/rules/php/auto.md +1 -0
  50. package/{scripts/check-php.mjs → rules/php/js/check.mjs} +1 -1
  51. package/{scripts/run-php.mjs → rules/php/js/run.mjs} +3 -3
  52. package/rules/rego/auto.md +1 -0
  53. package/{scripts/check-rego.mjs → rules/rego/js/check.mjs} +4 -4
  54. package/{scripts/lint-rego.mjs → rules/rego/js/lint.mjs} +1 -1
  55. package/rules/style-lint/auto.md +1 -0
  56. package/{scripts/check-style-lint.mjs → rules/style-lint/js/check.mjs} +1 -1
  57. package/rules/tauri/auto.md +1 -0
  58. package/{scripts/check-tauri.mjs → rules/tauri/js/check.mjs} +2 -2
  59. package/rules/text/auto.md +1 -0
  60. package/{scripts/check-text.mjs → rules/text/js/check.mjs} +2 -2
  61. package/{scripts/run-shellcheck-text.mjs → rules/text/js/run-shellcheck.mjs} +2 -2
  62. package/{scripts → rules/text/js}/run-v8r.mjs +2 -2
  63. package/{mdc → rules/text}/text.mdc +4 -0
  64. package/rules/vue/auto.md +1 -0
  65. package/{scripts/check-vue.mjs → rules/vue/js/check.mjs} +5 -5
  66. package/scripts/auto-rules.mjs +5 -5
  67. package/scripts/auto-skills.mjs +8 -6
  68. package/scripts/lint-conftest.mjs +13 -13
  69. package/scripts/sync-claude-config.mjs +70 -14
  70. package/scripts/utils/run-conftest-batch.mjs +9 -4
  71. package/skills/abie-clean/auto.md +1 -0
  72. package/skills/abie-kustomize/auto.md +1 -0
  73. package/skills/adr-normalize/SKILL.md +71 -0
  74. package/skills/adr-normalize/auto.md +1 -0
  75. package/skills/fix/auto.md +1 -0
  76. package/skills/lint/auto.md +1 -0
  77. package/skills/llm-patch/auto.md +1 -0
  78. package/skills/publish-telegram/auto.md +1 -0
  79. package/skills/taze/auto.md +1 -0
  80. package/bin/auto-rules.md +0 -59
  81. package/bin/auto-skills.md +0 -25
  82. package/mdc/adr.mdc +0 -86
  83. package/policy/adr/settings_json/settings_json.rego +0 -31
  84. package/policy/adr/settings_local_json/settings_local_json.rego +0 -28
  85. /package/{mdc → rules/abie}/abie.mdc +0 -0
  86. /package/{policy/abie → rules/abie/policy}/base_deployment_preem/base_deployment_preem.rego +0 -0
  87. /package/{policy/abie → rules/abie/policy}/base_deployment_preem/base_deployment_preem_test.rego +0 -0
  88. /package/{policy/abie → rules/abie/policy}/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +0 -0
  89. /package/{policy/abie → rules/abie/policy}/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +0 -0
  90. /package/{policy/abie → rules/abie/policy}/health_check_policy/health_check_policy.rego +0 -0
  91. /package/{policy/abie → rules/abie/policy}/health_check_policy/health_check_policy_test.rego +0 -0
  92. /package/{policy/abie → rules/abie/policy}/http_route_base/http_route_base.rego +0 -0
  93. /package/{policy/abie → rules/abie/policy}/http_route_base/http_route_base_test.rego +0 -0
  94. /package/{mdc → rules/bun}/bun.mdc +0 -0
  95. /package/{policy/bun → rules/bun/policy}/bunfig/bunfig.rego +0 -0
  96. /package/{policy/bun → rules/bun/policy}/package_json/package_json.rego +0 -0
  97. /package/{policy/bun → rules/bun/policy}/package_json/package_json_test.rego +0 -0
  98. /package/{mdc → rules/capacitor}/capacitor.mdc +0 -0
  99. /package/{policy/capacitor → rules/capacitor/policy}/package_json/package_json.rego +0 -0
  100. /package/{mdc → rules/changelog}/changelog.mdc +0 -0
  101. /package/{mdc → rules/ci4}/ci4.mdc +0 -0
  102. /package/{mdc → rules/docker}/docker.mdc +0 -0
  103. /package/{policy/docker → rules/docker/policy}/lint_docker_yml/lint_docker_yml.rego +0 -0
  104. /package/{policy/docker → rules/docker/policy}/lint_docker_yml/lint_docker_yml_test.rego +0 -0
  105. /package/{policy/docker → rules/docker/policy}/package_json/package_json.rego +0 -0
  106. /package/{policy/docker → rules/docker/policy}/package_json/package_json_test.rego +0 -0
  107. /package/{mdc → rules/ga}/ga.mdc +0 -0
  108. /package/{policy/ga → rules/ga/policy}/clean_ga_workflows/clean_ga_workflows.rego +0 -0
  109. /package/{policy/ga → rules/ga/policy}/clean_merged_branch/clean_merged_branch.rego +0 -0
  110. /package/{policy/ga → rules/ga/policy}/git_ai/git_ai.rego +0 -0
  111. /package/{policy/ga → rules/ga/policy}/lint_ga/lint_ga.rego +0 -0
  112. /package/{policy/ga → rules/ga/policy}/workflow_common/workflow_common.rego +0 -0
  113. /package/{mdc → rules/graphql}/graphql.mdc +0 -0
  114. /package/{policy/graphql → rules/graphql/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  115. /package/{policy/graphql → rules/graphql/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  116. /package/{mdc → rules/hasura}/hasura.mdc +0 -0
  117. /package/{policy/hasura → rules/hasura/policy}/svc_hl/svc_hl.rego +0 -0
  118. /package/{mdc → rules/image-avif}/image-avif.mdc +0 -0
  119. /package/{policy/image_avif → rules/image-avif/policy}/package_json/package_json.rego +0 -0
  120. /package/{policy/image_avif → rules/image-avif/policy}/package_json/package_json_test.rego +0 -0
  121. /package/{mdc → rules/image-compress}/image-compress.mdc +0 -0
  122. /package/{policy/image_compress → rules/image-compress/policy}/package_json/package_json.rego +0 -0
  123. /package/{mdc → rules/js-bun-db}/js-bun-db.mdc +0 -0
  124. /package/{policy/js_bun_db → rules/js-bun-db/policy}/package_json/package_json.rego +0 -0
  125. /package/{mdc → rules/js-bun-redis}/js-bun-redis.mdc +0 -0
  126. /package/{policy/js_bun_redis → rules/js-bun-redis/policy}/package_json/package_json.rego +0 -0
  127. /package/{mdc → rules/js-lint}/js-lint.mdc +0 -0
  128. /package/{policy/js_lint → rules/js-lint/policy}/lint_js_yml/lint_js_yml.rego +0 -0
  129. /package/{policy/js_lint → rules/js-lint/policy}/package_json/package_json.rego +0 -0
  130. /package/{policy/js_lint → rules/js-lint/policy}/package_json/package_json_test.rego +0 -0
  131. /package/{mdc → rules/js-mssql}/js-mssql.mdc +0 -0
  132. /package/{policy/js_mssql → rules/js-mssql/policy}/package_json/package_json.rego +0 -0
  133. /package/{mdc → rules/js-run}/js-run.mdc +0 -0
  134. /package/{policy/js_run → rules/js-run/policy}/configmap/configmap.rego +0 -0
  135. /package/{policy/js_run → rules/js-run/policy}/jsconfig/jsconfig.rego +0 -0
  136. /package/{policy/js_run → rules/js-run/policy}/jsconfig/jsconfig_test.rego +0 -0
  137. /package/{policy/js_run → rules/js-run/policy}/package_json/package_json.rego +0 -0
  138. /package/{mdc → rules/k8s}/k8s.mdc +0 -0
  139. /package/{policy/k8s → rules/k8s/policy}/base_kustomization/base_kustomization.rego +0 -0
  140. /package/{policy/k8s → rules/k8s/policy}/base_kustomization/base_kustomization_test.rego +0 -0
  141. /package/{policy/k8s → rules/k8s/policy}/base_manifest/base_manifest.rego +0 -0
  142. /package/{policy/k8s → rules/k8s/policy}/base_manifest/base_manifest_test.rego +0 -0
  143. /package/{policy/k8s → rules/k8s/policy}/gateway/gateway.rego +0 -0
  144. /package/{policy/k8s → rules/k8s/policy}/gateway/gateway_test.rego +0 -0
  145. /package/{policy/k8s → rules/k8s/policy}/hasura_configmap/hasura_configmap.rego +0 -0
  146. /package/{policy/k8s → rules/k8s/policy}/hasura_configmap/hasura_configmap_test.rego +0 -0
  147. /package/{policy/k8s → rules/k8s/policy}/hasura_httproute/hasura_httproute.rego +0 -0
  148. /package/{policy/k8s → rules/k8s/policy}/hasura_httproute/hasura_httproute_test.rego +0 -0
  149. /package/{policy/k8s → rules/k8s/policy}/hpa_pdb/hpa_pdb.rego +0 -0
  150. /package/{policy/k8s → rules/k8s/policy}/hpa_pdb/hpa_pdb_test.rego +0 -0
  151. /package/{policy/k8s → rules/k8s/policy}/kustomization/kustomization.rego +0 -0
  152. /package/{policy/k8s → rules/k8s/policy}/kustomization/kustomization_test.rego +0 -0
  153. /package/{policy/k8s → rules/k8s/policy}/manifest/manifest.rego +0 -0
  154. /package/{policy/k8s → rules/k8s/policy}/manifest/manifest_test.rego +0 -0
  155. /package/{policy/k8s → rules/k8s/policy}/svc_hl_yaml/svc_hl_yaml.rego +0 -0
  156. /package/{policy/k8s → rules/k8s/policy}/svc_hl_yaml/svc_hl_yaml_test.rego +0 -0
  157. /package/{policy/k8s → rules/k8s/policy}/svc_yaml/svc_yaml.rego +0 -0
  158. /package/{policy/k8s → rules/k8s/policy}/svc_yaml/svc_yaml_test.rego +0 -0
  159. /package/{mdc → rules/nginx-default-tpl}/nginx-default-tpl.mdc +0 -0
  160. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  161. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  162. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_settings/vscode_settings.rego +0 -0
  163. /package/{policy/nginx_default_tpl → rules/nginx-default-tpl/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  164. /package/{mdc → rules/npm-module}/npm-module.mdc +0 -0
  165. /package/{policy/npm_module → rules/npm-module/policy}/emit_types_config/emit_types_config.rego +0 -0
  166. /package/{policy/npm_module → rules/npm-module/policy}/npm_package_json/npm_package_json.rego +0 -0
  167. /package/{policy/npm_module → rules/npm-module/policy}/npm_package_json/npm_package_json_test.rego +0 -0
  168. /package/{policy/npm_module → rules/npm-module/policy}/npm_publish_yml/npm_publish_yml.rego +0 -0
  169. /package/{policy/npm_module → rules/npm-module/policy}/root_package_json/root_package_json.rego +0 -0
  170. /package/{mdc → rules/php}/php.mdc +0 -0
  171. /package/{policy/php → rules/php/policy}/lint_php_yml/lint_php_yml.rego +0 -0
  172. /package/{policy/php → rules/php/policy}/package_json/package_json.rego +0 -0
  173. /package/{policy/rego → rules/rego/policy}/package_json/package_json.rego +0 -0
  174. /package/{policy/rego → rules/rego/policy}/package_json/package_json_test.rego +0 -0
  175. /package/{policy/rego → rules/rego/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  176. /package/{policy/rego → rules/rego/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  177. /package/{policy/rego → rules/rego/policy}/vscode_settings/vscode_settings.rego +0 -0
  178. /package/{policy/rego → rules/rego/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  179. /package/{mdc → rules/rego}/rego.mdc +0 -0
  180. /package/{policy/style_lint → rules/style-lint/policy}/lint_style_yml/lint_style_yml.rego +0 -0
  181. /package/{policy/style_lint → rules/style-lint/policy}/package_json/package_json.rego +0 -0
  182. /package/{policy/style_lint → rules/style-lint/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  183. /package/{policy/style_lint → rules/style-lint/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  184. /package/{policy/style_lint → rules/style-lint/policy}/vscode_settings/vscode_settings.rego +0 -0
  185. /package/{policy/style_lint → rules/style-lint/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  186. /package/{mdc → rules/style-lint}/style-lint.mdc +0 -0
  187. /package/{policy/tauri → rules/tauri/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  188. /package/{policy/tauri → rules/tauri/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  189. /package/{mdc → rules/tauri}/tauri.mdc +0 -0
  190. /package/{policy/text → rules/text/policy}/cspell/cspell.rego +0 -0
  191. /package/{policy/text → rules/text/policy}/markdownlint/markdownlint.rego +0 -0
  192. /package/{policy/text → rules/text/policy}/markdownlint/markdownlint_test.rego +0 -0
  193. /package/{policy/text → rules/text/policy}/oxfmtrc/oxfmtrc.rego +0 -0
  194. /package/{policy/text → rules/text/policy}/package_json/package_json.rego +0 -0
  195. /package/{policy/text → rules/text/policy}/vscode_extensions/vscode_extensions.rego +0 -0
  196. /package/{policy/text → rules/text/policy}/vscode_extensions/vscode_extensions_test.rego +0 -0
  197. /package/{policy/text → rules/text/policy}/vscode_settings/vscode_settings.rego +0 -0
  198. /package/{policy/text → rules/text/policy}/vscode_settings/vscode_settings_test.rego +0 -0
  199. /package/{policy/vue → rules/vue/policy}/package_json/package_json.rego +0 -0
  200. /package/{mdc → rules/vue}/vue.mdc +0 -0
@@ -1,14 +1,17 @@
1
1
  /**
2
- * Перевіряє вимоги правила adr.mdc: ADR Stop-hook capture-decisions.sh у Claude Code.
2
+ * Перевіряє вимоги правила adr.mdc: ADR Stop-hook `capture-decisions.sh` і
3
+ * `normalize-decisions.sh` у Claude Code.
3
4
  *
4
5
  * Очікування:
5
- * - `.claude/hooks/capture-decisions.sh` існує і байт-у-байт збігається з канонічним
6
- * `.claude-template/hooks/capture-decisions.sh` пакета (sync керує файлом повністю).
7
- * - `.claude/settings.json` (project-shared) має managed-групу у `hooks.Stop`, яка
8
- * викликає цей bash-скрипт; маркер у `command` — `.claude/hooks/capture-decisions.sh`.
9
- * - `.claude/settings.local.json` (якщо існує) НЕ має дубля цієї managed-групи
10
- * після переходу на project-shared такий запис створив би два запуски на одну подію.
11
- * - `.gitignore` у корені містить шаблон, який покриває `.claude/hooks/capture-decisions.log`.
6
+ * - `.claude/hooks/capture-decisions.sh` та `.claude/hooks/normalize-decisions.sh`
7
+ * існують і байт-у-байт збігаються з канонічними `.claude-template/hooks/*`
8
+ * пакета (sync керує файлами повністю).
9
+ * - `.claude/settings.json` (project-shared) має managed-групи у `hooks.Stop` для
10
+ * обох скриптів (маркери у `command` самі шляхи до скриптів).
11
+ * - `.claude/settings.local.json` (якщо існує) НЕ має дублів цих managed-груп
12
+ * після переходу на project-shared такі записи створили б два запуски на одну подію.
13
+ * - `.gitignore` у корені містить шаблон, який покриває
14
+ * `.claude/hooks/capture-decisions.log` і `.claude/hooks/normalize-decisions.log`.
12
15
  *
13
16
  * LLM CLI (`claude` або `cursor-agent`) у `PATH` — інформативна перевірка: якщо жодного
14
17
  * немає, скрипт працює, але мовчки виходить, тому це warning, а не fail.
@@ -19,28 +22,50 @@ import { delimiter, dirname, join } from 'node:path'
19
22
  import { env } from 'node:process'
20
23
  import { fileURLToPath } from 'node:url'
21
24
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
25
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
26
+
27
+ /** Один hook-артефакт: bash-скрипт + його лог-файл, які перевіряємо однотипно. */
28
+ const HOOK_ARTIFACTS = /** @type {const} */ ([
29
+ { scriptName: 'capture-decisions.sh', logName: 'capture-decisions.log' },
30
+ { scriptName: 'normalize-decisions.sh', logName: 'normalize-decisions.log' }
31
+ ])
23
32
 
24
- const PROJECT_HOOK_PATH = '.claude/hooks/capture-decisions.sh'
25
33
  const PROJECT_SETTINGS_PATH = '.claude/settings.json'
26
- const PROJECT_LOG_PATH = '.claude/hooks/capture-decisions.log'
27
34
  const EOL_RE = /\r?\n/u
28
35
 
29
36
  const here = dirname(fileURLToPath(import.meta.url))
30
- /** Канонічний bundled-скрипт у пакеті джерело правди для звірки з проєктним. */
31
- const BUNDLED_HOOK_PATH = join(here, '..', '.claude-template', 'hooks', 'capture-decisions.sh')
37
+ const BUNDLED_HOOKS_DIR = join(here, '..', '..', '..', '.claude-template', 'hooks')
38
+
39
+ /**
40
+ * Відносний шлях до managed hook-скрипта у проєкті.
41
+ * @param {string} scriptName базове ім'я скрипта (наприклад `capture-decisions.sh`)
42
+ * @returns {string} `.claude/hooks/<scriptName>`
43
+ */
44
+ function projectHookPath(scriptName) {
45
+ return `.claude/hooks/${scriptName}`
46
+ }
47
+
48
+ /**
49
+ * Відносний шлях до лог-файлу managed hook'а у проєкті.
50
+ * @param {string} logName базове ім'я лог-файлу (наприклад `capture-decisions.log`)
51
+ * @returns {string} `.claude/hooks/<logName>`
52
+ */
53
+ function projectLogPath(logName) {
54
+ return `.claude/hooks/${logName}`
55
+ }
32
56
 
33
57
  /**
34
- * Чи містить рядок `.gitignore` шаблон, який покриває `.claude/hooks/capture-decisions.log`.
58
+ * Чи містить рядок `.gitignore` шаблон, який покриває цей конкретний лог-файл хука.
35
59
  * Враховує точний шлях, glob `.claude/hooks/*.log` та широкий glob `**\/*.log`.
36
60
  * @param {string} line одна нормалізована (trim) лінія `.gitignore`
37
- * @returns {boolean} `true`, якщо лінія матчить лог-файл хука
61
+ * @param {string} logPath шлях `.claude/hooks/<name>.log`, який треба покрити
62
+ * @returns {boolean} `true`, якщо лінія матчить цей лог-файл
38
63
  */
39
- function gitignoreLineCoversHookLog(line) {
64
+ function gitignoreLineCoversHookLog(line, logPath) {
40
65
  if (!line || line.startsWith('#')) {
41
66
  return false
42
67
  }
43
- if (line === PROJECT_LOG_PATH) {
68
+ if (line === logPath) {
44
69
  return true
45
70
  }
46
71
  if (line === '.claude/hooks/*.log' || line === '.claude/hooks/**/*.log') {
@@ -53,28 +78,28 @@ function gitignoreLineCoversHookLog(line) {
53
78
  }
54
79
 
55
80
  /**
56
- * Перевіряє наявність і канонічність `.claude/hooks/capture-decisions.sh` у проєкті.
81
+ * Перевіряє наявність і канонічність одного hook-скрипта.
57
82
  * @param {import('./utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
83
+ * @param {string} scriptName базове ім'я скрипта (наприклад `capture-decisions.sh`)
58
84
  * @returns {Promise<void>}
59
85
  */
60
- async function checkHookScript(reporter) {
86
+ async function checkHookScript(reporter, scriptName) {
61
87
  const { pass, fail } = reporter
62
- if (!existsSync(PROJECT_HOOK_PATH)) {
63
- fail(`${PROJECT_HOOK_PATH} не існує — запусти \`npx @nitra/cursor\` (правило adr копіює канонічний скрипт)`)
88
+ const projectPath = projectHookPath(scriptName)
89
+ const bundledPath = join(BUNDLED_HOOKS_DIR, scriptName)
90
+ if (!existsSync(projectPath)) {
91
+ fail(`${projectPath} не існує — запусти \`npx @nitra/cursor\` (правило adr копіює канонічний скрипт)`)
64
92
  return
65
93
  }
66
- if (!existsSync(BUNDLED_HOOK_PATH)) {
67
- fail(`канонічний скрипт у пакеті не знайдено: ${BUNDLED_HOOK_PATH} — перевстанови @nitra/cursor`)
94
+ if (!existsSync(bundledPath)) {
95
+ fail(`канонічний скрипт у пакеті не знайдено: ${bundledPath} — перевстанови @nitra/cursor`)
68
96
  return
69
97
  }
70
- const [project, bundled] = await Promise.all([
71
- readFile(PROJECT_HOOK_PATH, 'utf8'),
72
- readFile(BUNDLED_HOOK_PATH, 'utf8')
73
- ])
98
+ const [project, bundled] = await Promise.all([readFile(projectPath, 'utf8'), readFile(bundledPath, 'utf8')])
74
99
  if (project === bundled) {
75
- pass(`${PROJECT_HOOK_PATH} збігається з канонічним`)
100
+ pass(`${projectPath} збігається з канонічним`)
76
101
  } else {
77
- fail(`${PROJECT_HOOK_PATH} відрізняється від канонічного — запусти \`npx @nitra/cursor\` для повторного синку`)
102
+ fail(`${projectPath} відрізняється від канонічного — запусти \`npx @nitra/cursor\` для повторного синку`)
78
103
  }
79
104
  }
80
105
 
@@ -95,25 +120,42 @@ function checkProjectSettings(reporter) {
95
120
  }
96
121
 
97
122
  /**
98
- * Перевіряє `.gitignore` на ігнорування лог-файлу хука.
123
+ * Перевіряє `.gitignore` на ігнорування лог-файлу одного хука.
124
+ * @param {import('./utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
125
+ * @param {string} logName базове ім'я лог-файлу (наприклад `capture-decisions.log`)
126
+ * @param {string} gitignoreContent попередньо прочитаний вміст `.gitignore`
127
+ * @returns {void}
128
+ */
129
+ function checkGitignoreForLog(reporter, logName, gitignoreContent) {
130
+ const { pass, fail } = reporter
131
+ const logPath = projectLogPath(logName)
132
+ const covers = gitignoreContent
133
+ .split(EOL_RE)
134
+ .map(l => l.trim())
135
+ .some(line => gitignoreLineCoversHookLog(line, logPath))
136
+ if (covers) {
137
+ pass(`.gitignore покриває ${logPath}`)
138
+ } else {
139
+ fail(`.gitignore не ігнорує \`${logPath}\` — додай цей рядок`)
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Перевіряє `.gitignore` для всіх hook-логів одним проходом.
99
145
  * @param {import('./utils/check-reporter.mjs').CheckReporter} reporter репортер для збору результатів
100
146
  * @returns {Promise<void>}
101
147
  */
102
148
  async function checkGitignore(reporter) {
103
- const { pass, fail } = reporter
149
+ const { fail } = reporter
104
150
  if (!existsSync('.gitignore')) {
105
- fail(`.gitignore не існує додай рядок \`${PROJECT_LOG_PATH}\``)
151
+ for (const { logName } of HOOK_ARTIFACTS) {
152
+ fail(`.gitignore не існує — додай рядок \`${projectLogPath(logName)}\``)
153
+ }
106
154
  return
107
155
  }
108
156
  const content = await readFile('.gitignore', 'utf8')
109
- const covers = content
110
- .split(EOL_RE)
111
- .map(l => l.trim())
112
- .some(line => gitignoreLineCoversHookLog(line))
113
- if (covers) {
114
- pass(`.gitignore покриває ${PROJECT_LOG_PATH}`)
115
- } else {
116
- fail(`.gitignore не ігнорує \`${PROJECT_LOG_PATH}\` — додай цей рядок`)
157
+ for (const { logName } of HOOK_ARTIFACTS) {
158
+ checkGitignoreForLog(reporter, logName, content)
117
159
  }
118
160
  }
119
161
 
@@ -166,7 +208,9 @@ function checkLlmCliAvailable(reporter) {
166
208
  */
167
209
  export async function check() {
168
210
  const reporter = createCheckReporter()
169
- await checkHookScript(reporter)
211
+ for (const { scriptName } of HOOK_ARTIFACTS) {
212
+ await checkHookScript(reporter, scriptName)
213
+ }
170
214
  checkProjectSettings(reporter)
171
215
  await checkGitignore(reporter)
172
216
  checkLlmCliAvailable(reporter)
@@ -0,0 +1,37 @@
1
+ # Перевірка `.claude/settings.json` для правила adr.mdc:
2
+ # `hooks.Stop[*]` має містити дві managed-групи — capture і normalize — у
3
+ # кожній хоча б один елемент `hooks[]` з відповідним маркером у `command`.
4
+ #
5
+ # Запуск (локально):
6
+ # conftest test .claude/settings.json -p npm/rules/adr/policy \
7
+ # --namespace adr.settings_json
8
+ #
9
+ # Hash-порівняння bash-скриптів з канонічними bundled-варіантами і `.gitignore`-перевірки
10
+ # — у JS (`js/check.mjs`).
11
+ #
12
+ # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
13
+ # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
14
+ # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
15
+ package adr.settings_json
16
+
17
+ import rego.v1
18
+
19
+ capture_marker := ".claude/hooks/capture-decisions.sh"
20
+ normalize_marker := ".claude/hooks/normalize-decisions.sh"
21
+
22
+ deny contains msg if {
23
+ not has_stop_hook_with_marker(capture_marker)
24
+ msg := ".claude/settings.json: відсутній Stop-hook для `capture-decisions.sh` у hooks.Stop (adr.mdc)"
25
+ }
26
+
27
+ deny contains msg if {
28
+ not has_stop_hook_with_marker(normalize_marker)
29
+ msg := ".claude/settings.json: відсутній Stop-hook для `normalize-decisions.sh` у hooks.Stop (adr.mdc)"
30
+ }
31
+
32
+ # Чи є в `hooks.Stop[*].hooks[*].command` рядок з заданим маркером.
33
+ has_stop_hook_with_marker(marker) if {
34
+ some group in object.get(object.get(input, "hooks", {}), "Stop", [])
35
+ some hook in object.get(group, "hooks", [])
36
+ contains(object.get(hook, "command", ""), marker)
37
+ }
@@ -0,0 +1,40 @@
1
+ # Перевірка `.claude/settings.local.json` для правила adr.mdc: після переходу на
2
+ # project-shared `settings.json` цей файл (якщо є) НЕ повинен мати дубля жодного
3
+ # з керованих Stop-хуків (`capture-decisions.sh` або `normalize-decisions.sh`),
4
+ # інакше відповідний скрипт виконається двічі на одну подію.
5
+ #
6
+ # Запуск (локально):
7
+ # conftest test .claude/settings.local.json -p npm/rules/adr/policy \
8
+ # --namespace adr.settings_local_json
9
+ #
10
+ # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
11
+ # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
12
+ # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
13
+ package adr.settings_local_json
14
+
15
+ import rego.v1
16
+
17
+ capture_marker := ".claude/hooks/capture-decisions.sh"
18
+ normalize_marker := ".claude/hooks/normalize-decisions.sh"
19
+
20
+ deny contains msg if {
21
+ has_stop_hook_with_marker(capture_marker)
22
+ msg := concat(" ", [
23
+ ".claude/settings.local.json: видали дубль Stop-хука для",
24
+ "`capture-decisions.sh` — він уже у project-shared settings.json (adr.mdc)",
25
+ ])
26
+ }
27
+
28
+ deny contains msg if {
29
+ has_stop_hook_with_marker(normalize_marker)
30
+ msg := concat(" ", [
31
+ ".claude/settings.local.json: видали дубль Stop-хука для",
32
+ "`normalize-decisions.sh` — він уже у project-shared settings.json (adr.mdc)",
33
+ ])
34
+ }
35
+
36
+ has_stop_hook_with_marker(marker) if {
37
+ some group in object.get(object.get(input, "hooks", {}), "Stop", [])
38
+ some hook in object.get(group, "hooks", [])
39
+ contains(object.get(hook, "command", ""), marker)
40
+ }
@@ -0,0 +1 @@
1
+ якщо в корені проекту є package.json
@@ -18,7 +18,7 @@
18
18
  import { existsSync } from 'node:fs'
19
19
  import { readFile } from 'node:fs/promises'
20
20
 
21
- import { createCheckReporter } from './utils/check-reporter.mjs'
21
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
22
 
23
23
  // Перевірка `devDependencies` кореневого `package.json` (дозволено лише `@nitra/*`)
24
24
  // — у rego (`npm/policy/bun/package_json/`). JS-копії `isAllowedRootDevDependency`
@@ -0,0 +1 @@
1
+ якщо в проекті є хоч один файл capacitor.config.json
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readdir, readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
29
 
30
30
  /** Мінімальна допустима мажорна версія Capacitor (capacitor.mdc) */
31
31
  const MIN_CAPACITOR_MAJOR = 8
@@ -0,0 +1 @@
1
+ [bun]
@@ -27,8 +27,8 @@ import { readFile } from 'node:fs/promises'
27
27
  import { join } from 'node:path'
28
28
  import { promisify } from 'node:util'
29
29
 
30
- import { createCheckReporter } from './utils/check-reporter.mjs'
31
- import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
30
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
31
+ import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
32
32
 
33
33
  const execFileAsync = promisify(execFile)
34
34
 
@@ -0,0 +1 @@
1
+ якщо в проекті є хоч один Dockerfile
@@ -30,11 +30,11 @@
30
30
  import { readFile } from 'node:fs/promises'
31
31
  import { basename } from 'node:path'
32
32
 
33
- import { getMirrorGcrHint, getFromImageToken } from './utils/docker-mirror.mjs'
34
- import { lintDockerfileWithHadolint, posixRel } from './utils/docker-hadolint.mjs'
35
- import { createCheckReporter } from './utils/check-reporter.mjs'
36
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
37
- import { walkDir } from './utils/walkDir.mjs'
33
+ import { getMirrorGcrHint, getFromImageToken } from '../../../scripts/utils/docker-mirror.mjs'
34
+ import { lintDockerfileWithHadolint, posixRel } from '../../../scripts/utils/docker-hadolint.mjs'
35
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
36
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
37
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
38
38
 
39
39
  const NEWLINE_RE = /\r?\n/
40
40
  const BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu
@@ -9,11 +9,11 @@
9
9
  */
10
10
  import { basename } from 'node:path'
11
11
 
12
- import { isRunAsCli } from './cli-entry.mjs'
13
- import { lintDockerfileWithHadolint, posixRel } from './utils/docker-hadolint.mjs'
14
- import { createCheckReporter } from './utils/check-reporter.mjs'
15
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
16
- import { walkDir } from './utils/walkDir.mjs'
12
+ import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
13
+ import { lintDockerfileWithHadolint, posixRel } from '../../../scripts/utils/docker-hadolint.mjs'
14
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
15
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
16
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
17
17
 
18
18
  /**
19
19
  * Чи входить файл до набору lint-docker: Dockerfile або *.Dockerfile (*.dockerfile).
@@ -0,0 +1 @@
1
+ якщо присутня директорія .github/workflows
@@ -19,10 +19,10 @@ import { readdir, readFile } from 'node:fs/promises'
19
19
  import { execFileSync } from 'node:child_process'
20
20
  import { join } from 'node:path'
21
21
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
23
- import { eventPathsIncludeExact, parseWorkflowYaml } from './utils/gha-workflow.mjs'
24
- import { resolveCmd } from './utils/resolve-cmd.mjs'
25
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
22
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
+ import { eventPathsIncludeExact, parseWorkflowYaml } from '../../../scripts/utils/gha-workflow.mjs'
24
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
25
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
26
26
 
27
27
  /** Шаблони наявності MegaLinter у вмісті workflow */
28
28
  const MEGALINTER_USE_PATTERNS = [/oxsecurity\/megalinter-action/i, /megalinter\/megalinter/i]
@@ -22,8 +22,8 @@
22
22
  import { spawnSync } from 'node:child_process'
23
23
  import { platform } from 'node:process'
24
24
 
25
- import { check as checkGa } from './check-ga.mjs'
26
- import { resolveCmd } from './utils/resolve-cmd.mjs'
25
+ import { check as checkGa } from './check.mjs'
26
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
27
27
 
28
28
  /**
29
29
  * Опис залежності preflight-ом: бінарник, для чого потрібен, і команди встановлення.
@@ -0,0 +1 @@
1
+ якщо хоч в одному js або vue файлі присутній gql` темплейт літерал
@@ -10,15 +10,15 @@ import { existsSync } from 'node:fs'
10
10
  import { readFile } from 'node:fs/promises'
11
11
  import { relative } from 'node:path'
12
12
 
13
- import { createCheckReporter } from './utils/check-reporter.mjs'
13
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
14
14
  import {
15
15
  isGqlScanSourceFile,
16
16
  shouldSkipFileForGqlScan,
17
17
  sourceFileHasGqlTaggedTemplate
18
- } from './utils/graphql-gql-scan.mjs'
19
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
20
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
21
- import { walkDir } from './utils/walkDir.mjs'
18
+ } from '../../../scripts/utils/graphql-gql-scan.mjs'
19
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
20
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
21
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
22
22
 
23
23
  /** Очікуваний файл GraphQL Config у корені (graphql.mdc). */
24
24
  export const GRAPHQL_RC_FILENAME = '.graphqlrc.yml'
@@ -0,0 +1 @@
1
+ якщо в директорії присутній config.yaml, який містить рядок `metadata_directory: metadata`
@@ -27,10 +27,10 @@ import { basename, join, relative } from 'node:path'
27
27
 
28
28
  import { parseAllDocuments } from 'yaml'
29
29
 
30
- import { getRepositoryUrl } from './auto-rules.mjs'
31
- import { createCheckReporter } from './utils/check-reporter.mjs'
32
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
33
- import { walkDir } from './utils/walkDir.mjs'
30
+ import { getRepositoryUrl } from '../../../scripts/auto-rules.mjs'
31
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
32
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
33
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
34
34
 
35
35
  const NITRA_REPOSITORY_URL_MARKER = 'https://github.com/nitra/'
36
36
  const ABIE_REPOSITORY_URL_MARKER = 'https://github.com/abinbevefes/'
@@ -0,0 +1 @@
1
+ [vue, image-compress]
@@ -25,11 +25,11 @@ import { join, relative } from 'node:path'
25
25
  import { spawnSync } from 'node:child_process'
26
26
  import { env } from 'node:process'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
29
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
30
- import { resolveCmd } from './utils/resolve-cmd.mjs'
31
- import { walkDir } from './utils/walkDir.mjs'
32
- import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
30
+ import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
31
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
32
+ import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
33
33
 
34
34
  /** Імʼя CLI-пакета, який генерує AVIF. */
35
35
  const MINIFY_PACKAGE_NAME = '@nitra/minify-image'
@@ -0,0 +1 @@
1
+ [bun]
@@ -19,7 +19,7 @@
19
19
  import { existsSync } from 'node:fs'
20
20
  import { readFile } from 'node:fs/promises'
21
21
 
22
- import { createCheckReporter } from './utils/check-reporter.mjs'
22
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
23
 
24
24
  /** Імʼя committed-кешу (sha1 + originalSize + size) у `@nitra/minify-image` ≥ 3.2.0. */
25
25
  const HASH_CACHE_FILENAME = '.n-minify-image.tsv'
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет pg, pg-format або mysql2 або є імпорт sql/SQL з Bun (приклад: import { sql } from "bun")
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from './utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
29
  import {
30
30
  findBunSqlPerRequestConnectionInText,
31
31
  findBunSqlPgLeftoverCallInText,
@@ -36,10 +36,10 @@ import {
36
36
  findUnsafeBunSqlInListMissingEmptyGuardInText,
37
37
  isBunSqlScanSourceFile,
38
38
  textHasBunSqlImport
39
- } from './utils/bun-sql-scan.mjs'
40
- import { findAllPackageJsonPaths } from './utils/find-package-json-paths.mjs'
41
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
42
- import { walkDir } from './utils/walkDir.mjs'
39
+ } from '../../../scripts/utils/bun-sql-scan.mjs'
40
+ import { findAllPackageJsonPaths } from '../../../scripts/utils/find-package-json-paths.mjs'
41
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
42
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
43
43
 
44
44
  /**
45
45
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану Bun SQL патернів.
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет ioredis або node-redis
@@ -14,10 +14,10 @@ import { existsSync } from 'node:fs'
14
14
  import { readFile } from 'node:fs/promises'
15
15
  import { join, relative } from 'node:path'
16
16
 
17
- import { createCheckReporter } from './utils/check-reporter.mjs'
18
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
19
- import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from './utils/redis-imports.mjs'
20
- import { walkDir } from './utils/walkDir.mjs'
17
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
18
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
19
+ import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from '../../../scripts/utils/redis-imports.mjs'
20
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
21
21
 
22
22
  /**
23
23
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану заборонених redis-імпортів.
@@ -0,0 +1 @@
1
+ якщо присутній хоч один js файл
@@ -16,7 +16,7 @@ import { copyFile, readFile } from 'node:fs/promises'
16
16
  import { dirname, join } from 'node:path'
17
17
  import { fileURLToPath } from 'node:url'
18
18
 
19
- import { createCheckReporter } from './utils/check-reporter.mjs'
19
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
20
20
 
21
21
  /** Шлях до канонічного oxlint JSON у цьому пакеті (для перевірки та тестів). */
22
22
  export const OXLINT_CANONICAL_JSON_PATH = join(
@@ -0,0 +1 @@
1
+ якщо в хоч одному package.json в секції dependencies присутній пакет mssql
@@ -12,8 +12,8 @@ import { existsSync } from 'node:fs'
12
12
  import { readFile } from 'node:fs/promises'
13
13
  import { join, relative } from 'node:path'
14
14
 
15
- import { createCheckReporter } from './utils/check-reporter.mjs'
16
- import { findAllPackageJsonPaths } from './utils/find-package-json-paths.mjs'
15
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
16
+ import { findAllPackageJsonPaths } from '../../../scripts/utils/find-package-json-paths.mjs'
17
17
  import {
18
18
  findMssqlPerRequestConnectionInText,
19
19
  findSharedMssqlRequestInText,
@@ -22,9 +22,9 @@ import {
22
22
  findUnsafeMssqlInListUnparsedInText,
23
23
  findUnsafeMssqlInListMissingEmptyGuardInText,
24
24
  isMssqlScanSourceFile
25
- } from './utils/mssql-pool-scan.mjs'
26
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
27
- import { walkDir } from './utils/walkDir.mjs'
25
+ } from '../../../scripts/utils/mssql-pool-scan.mjs'
26
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
27
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
28
28
 
29
29
  const VERSION_PREFIX_RE = /^[\^~>=<]+\s*/u
30
30
  const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/u
@@ -0,0 +1 @@
1
+ якщо це вкладена директорія з package.json (не в корені) та в devDependencies немає vite
@@ -37,21 +37,21 @@ import {
37
37
  findBunyanImportsInText,
38
38
  isBunyanScanSourceFile,
39
39
  shouldSkipFileForBunyanScan
40
- } from './utils/bunyan-imports.mjs'
41
- import { findUncheckedProcessEnvInText, isCheckEnvScanSourceFile } from './utils/check-env-scan.mjs'
42
- import { createCheckReporter } from './utils/check-reporter.mjs'
43
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
44
- import { findConnFileRuleViolations, isConnFileRulesSourceFile } from './utils/conn-file-rules.mjs'
40
+ } from '../../../scripts/utils/bunyan-imports.mjs'
41
+ import { findUncheckedProcessEnvInText, isCheckEnvScanSourceFile } from '../../../scripts/utils/check-env-scan.mjs'
42
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
43
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
44
+ import { findConnFileRuleViolations, isConnFileRulesSourceFile } from '../../../scripts/utils/conn-file-rules.mjs'
45
45
  import {
46
46
  findConnFactoryImportsInText,
47
47
  isConnImportsScanSourceFile,
48
48
  isInsideConnDir,
49
49
  resolveConnDirFromPackageJson
50
- } from './utils/conn-imports-scan.mjs'
51
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
52
- import { findPromiseSetTimeoutInText, isPromiseSetTimeoutScanSourceFile } from './utils/promise-settimeout-scan.mjs'
53
- import { walkDir } from './utils/walkDir.mjs'
54
- import { getMonorepoPackageRootDirs } from './utils/workspaces.mjs'
50
+ } from '../../../scripts/utils/conn-imports-scan.mjs'
51
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
52
+ import { findPromiseSetTimeoutInText, isPromiseSetTimeoutScanSourceFile } from '../../../scripts/utils/promise-settimeout-scan.mjs'
53
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
54
+ import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
55
55
 
56
56
  /**
57
57
  * Чи існує непорожній за змістом маркер каталогу `src/` (рекомендована структура js-run).
@@ -92,7 +92,7 @@ function checkBackendJsconfigWhenSrcPresent(rootDir, absPackageRoot, label, fail
92
92
  return
93
93
  }
94
94
  const violations = runConftestBatch({
95
- policyDirRel: 'js_run/jsconfig',
95
+ policyDirRel: 'js-run/jsconfig',
96
96
  namespace: 'js_run.jsconfig',
97
97
  files: [jcPath]
98
98
  })
@@ -0,0 +1 @@
1
+ якщо присутня хоч одна директорія k8s
@@ -134,10 +134,10 @@ import { basename, dirname, join, relative, resolve } from 'node:path'
134
134
 
135
135
  import { isSeq, parseAllDocuments, parseDocument } from 'yaml'
136
136
 
137
- import { createCheckReporter } from './utils/check-reporter.mjs'
138
- import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
139
- import { runConftestBatch } from './utils/run-conftest-batch.mjs'
140
- import { walkDir } from './utils/walkDir.mjs'
137
+ import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
138
+ import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
139
+ import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
140
+ import { walkDir } from '../../../scripts/utils/walkDir.mjs'
141
141
 
142
142
  /** Версія набору схем yannh — узгоджено з k8s.mdc */
143
143
  const YANNH_PIN = 'v1.33.9-standalone-strict'