@7n/rules 1.27.0 → 1.28.1

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 (268) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -5
  3. package/schemas/v8r-catalog.json +10 -1
  4. package/scripts/auto-rules.mjs +2 -3
  5. package/scripts/docs/auto-rules.md +1 -1
  6. package/scripts/lib/docs/glob-to-regex.md +31 -0
  7. package/scripts/lib/docs/index.md +2 -0
  8. package/scripts/lib/docs/js-source-signals.md +32 -0
  9. package/scripts/lib/glob-to-regex.mjs +79 -0
  10. package/scripts/lib/js-source-signals.mjs +50 -0
  11. package/scripts/utils/ast-scan-utils.mjs +2 -2
  12. package/scripts/utils/docs/ast-scan-utils.md +1 -1
  13. package/rules/bun/bunfig/bunfig.mdc +0 -17
  14. package/rules/bun/bunfig/bunfig.rego +0 -29
  15. package/rules/bun/bunfig/concern.json +0 -9
  16. package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +0 -2
  17. package/rules/bun/docs/index.md +0 -11
  18. package/rules/bun/layout/concern.json +0 -16
  19. package/rules/bun/layout/docs/fix-layout.md +0 -29
  20. package/rules/bun/layout/docs/main.md +0 -34
  21. package/rules/bun/layout/fix-layout.mjs +0 -63
  22. package/rules/bun/layout/layout.mdc +0 -60
  23. package/rules/bun/layout/main.mjs +0 -53
  24. package/rules/bun/licensee/concern.json +0 -7
  25. package/rules/bun/licensee/docs/fix-licensee.md +0 -27
  26. package/rules/bun/licensee/docs/index.md +0 -12
  27. package/rules/bun/licensee/docs/main.md +0 -30
  28. package/rules/bun/licensee/fix-licensee.mjs +0 -31
  29. package/rules/bun/licensee/main.mjs +0 -68
  30. package/rules/bun/lint-surface/concern.json +0 -3
  31. package/rules/bun/lint-surface/lint-surface.mdc +0 -13
  32. package/rules/bun/main.json +0 -1
  33. package/rules/bun/main.mdc +0 -11
  34. package/rules/bun/package_json/concern.json +0 -9
  35. package/rules/bun/package_json/docs/fix-package_json.md +0 -28
  36. package/rules/bun/package_json/docs/index.md +0 -9
  37. package/rules/bun/package_json/fix-package_json.mjs +0 -311
  38. package/rules/bun/package_json/package_json.mdc +0 -14
  39. package/rules/bun/package_json/package_json.rego +0 -64
  40. package/rules/bun/package_json/template/package.json.deny.json +0 -4
  41. package/rules/js/check/check.mdc +0 -26
  42. package/rules/js/check/concern.json +0 -19
  43. package/rules/js/check/docs/eslint-config.md +0 -56
  44. package/rules/js/check/docs/fix-check.md +0 -48
  45. package/rules/js/check/docs/index.md +0 -13
  46. package/rules/js/check/docs/main.md +0 -48
  47. package/rules/js/check/eslint-config.mjs +0 -262
  48. package/rules/js/check/fix-check.mjs +0 -82
  49. package/rules/js/check/main.mjs +0 -310
  50. package/rules/js/dep-policy/concern.json +0 -4
  51. package/rules/js/dep-policy/dep-policy.mdc +0 -36
  52. package/rules/js/dep-policy/docs/main.md +0 -35
  53. package/rules/js/dep-policy/main.mjs +0 -99
  54. package/rules/js/docs/index.md +0 -11
  55. package/rules/js/eslint/concern.json +0 -8
  56. package/rules/js/eslint/docs/fix-eslint.md +0 -50
  57. package/rules/js/eslint/docs/fix-worker.md +0 -31
  58. package/rules/js/eslint/docs/index.md +0 -11
  59. package/rules/js/eslint/docs/main.md +0 -35
  60. package/rules/js/eslint/fix-eslint.mjs +0 -160
  61. package/rules/js/eslint/fix-worker.mjs +0 -139
  62. package/rules/js/eslint/main.mjs +0 -115
  63. package/rules/js/file-extensions/concern.json +0 -3
  64. package/rules/js/file-extensions/file-extensions.mdc +0 -12
  65. package/rules/js/jscpd_config/concern.json +0 -11
  66. package/rules/js/jscpd_config/docs/fix-jscpd_config.md +0 -26
  67. package/rules/js/jscpd_config/docs/index.md +0 -9
  68. package/rules/js/jscpd_config/fix-jscpd_config.mjs +0 -3
  69. package/rules/js/jscpd_config/jscpd_config.mdc +0 -42
  70. package/rules/js/jscpd_config/jscpd_config.rego +0 -44
  71. package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +0 -7
  72. package/rules/js/jscpd_duplicates/concern.json +0 -7
  73. package/rules/js/jscpd_duplicates/docs/main.md +0 -29
  74. package/rules/js/jscpd_duplicates/main.mjs +0 -69
  75. package/rules/js/knip/concern.json +0 -7
  76. package/rules/js/knip/docs/main.md +0 -32
  77. package/rules/js/knip/knip.mdc +0 -15
  78. package/rules/js/knip/main.mjs +0 -68
  79. package/rules/js/lint-findings/concern.json +0 -3
  80. package/rules/js/lint-findings/docs/main.md +0 -41
  81. package/rules/js/lint-findings/main.mjs +0 -125
  82. package/rules/js/main.json +0 -1
  83. package/rules/js/main.mdc +0 -18
  84. package/rules/js/package_json/concern.json +0 -9
  85. package/rules/js/package_json/docs/fix-package_json.md +0 -26
  86. package/rules/js/package_json/docs/index.md +0 -9
  87. package/rules/js/package_json/fix-package_json.mjs +0 -3
  88. package/rules/js/package_json/package_json.mdc +0 -15
  89. package/rules/js/package_json/package_json.rego +0 -142
  90. package/rules/js/package_json/template/package.json.snippet.json +0 -6
  91. package/rules/js/tooling/concern.json +0 -3
  92. package/rules/js/tooling/data/tooling/knip-canonical.json +0 -30
  93. package/rules/js/tooling/data/tooling/oxlint-canonical.json +0 -400
  94. package/rules/js/tooling/docs/main.md +0 -53
  95. package/rules/js/tooling/main.mjs +0 -183
  96. package/rules/js/utils_imports/concern.json +0 -4
  97. package/rules/js/utils_imports/docs/main.md +0 -50
  98. package/rules/js/utils_imports/main.mjs +0 -185
  99. package/rules/js/utils_imports/utils_imports.mdc +0 -15
  100. package/rules/js/vscode_extensions/concern.json +0 -11
  101. package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +0 -25
  102. package/rules/js/vscode_extensions/docs/index.md +0 -11
  103. package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +0 -1
  104. package/rules/js/vscode_extensions/template/extensions.json.snippet.json +0 -6
  105. package/rules/js/vscode_extensions/vscode_extensions.mdc +0 -11
  106. package/rules/js/vscode_extensions/vscode_extensions.rego +0 -12
  107. package/rules/js-bun-db/connection/concern.json +0 -3
  108. package/rules/js-bun-db/connection/connection.mdc +0 -42
  109. package/rules/js-bun-db/docs/index.md +0 -11
  110. package/rules/js-bun-db/lib/bun-sql-scan.mjs +0 -1055
  111. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +0 -63
  112. package/rules/js-bun-db/lib/docs/index.md +0 -11
  113. package/rules/js-bun-db/main.json +0 -1
  114. package/rules/js-bun-db/main.mdc +0 -8
  115. package/rules/js-bun-db/package_json/concern.json +0 -9
  116. package/rules/js-bun-db/package_json/package_json.mdc +0 -31
  117. package/rules/js-bun-db/package_json/package_json.rego +0 -15
  118. package/rules/js-bun-db/package_json/template/package.json.deny.json +0 -6
  119. package/rules/js-bun-db/pg_format_identifiers/concern.json +0 -3
  120. package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +0 -104
  121. package/rules/js-bun-db/safety/concern.json +0 -4
  122. package/rules/js-bun-db/safety/docs/main.md +0 -34
  123. package/rules/js-bun-db/safety/main.mjs +0 -430
  124. package/rules/js-bun-db/safety/safety.mdc +0 -458
  125. package/rules/js-bun-redis/docs/index.md +0 -11
  126. package/rules/js-bun-redis/imports/concern.json +0 -4
  127. package/rules/js-bun-redis/imports/docs/main.md +0 -36
  128. package/rules/js-bun-redis/imports/imports.mdc +0 -47
  129. package/rules/js-bun-redis/imports/main.mjs +0 -88
  130. package/rules/js-bun-redis/lib/docs/index.md +0 -11
  131. package/rules/js-bun-redis/lib/docs/redis-imports.md +0 -227
  132. package/rules/js-bun-redis/lib/redis-imports.mjs +0 -130
  133. package/rules/js-bun-redis/main.json +0 -1
  134. package/rules/js-bun-redis/main.mdc +0 -8
  135. package/rules/js-bun-redis/package_json/concern.json +0 -9
  136. package/rules/js-bun-redis/package_json/package_json.mdc +0 -11
  137. package/rules/js-bun-redis/package_json/package_json.rego +0 -15
  138. package/rules/js-bun-redis/package_json/template/package.json.deny.json +0 -12
  139. package/rules/js-mssql/deps/concern.json +0 -4
  140. package/rules/js-mssql/deps/docs/main.md +0 -33
  141. package/rules/js-mssql/deps/main.mjs +0 -297
  142. package/rules/js-mssql/docs/index.md +0 -11
  143. package/rules/js-mssql/lib/docs/index.md +0 -11
  144. package/rules/js-mssql/lib/docs/mssql-pool-scan.md +0 -380
  145. package/rules/js-mssql/lib/mssql-pool-scan.mjs +0 -610
  146. package/rules/js-mssql/main.json +0 -1
  147. package/rules/js-mssql/main.mdc +0 -144
  148. package/rules/js-mssql/mssql-tvp/concern.json +0 -3
  149. package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +0 -77
  150. package/rules/js-mssql/package_json/concern.json +0 -9
  151. package/rules/js-mssql/package_json/package_json.mdc +0 -9
  152. package/rules/js-mssql/package_json/package_json.rego +0 -57
  153. package/rules/js-run/configmap/concern.json +0 -9
  154. package/rules/js-run/configmap/configmap.mdc +0 -37
  155. package/rules/js-run/configmap/configmap.rego +0 -21
  156. package/rules/js-run/configmap/template/configmap.yaml.contains.yml +0 -4
  157. package/rules/js-run/docs/index.md +0 -11
  158. package/rules/js-run/jsconfig/concern.json +0 -9
  159. package/rules/js-run/jsconfig/docs/fix-jsconfig.md +0 -29
  160. package/rules/js-run/jsconfig/docs/index.md +0 -9
  161. package/rules/js-run/jsconfig/fix-jsconfig.mjs +0 -119
  162. package/rules/js-run/jsconfig/jsconfig.mdc +0 -48
  163. package/rules/js-run/jsconfig/jsconfig.rego +0 -59
  164. package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +0 -10
  165. package/rules/js-run/lib/bunyan-imports.mjs +0 -98
  166. package/rules/js-run/lib/check-env-scan.mjs +0 -338
  167. package/rules/js-run/lib/conn-file-rules.mjs +0 -214
  168. package/rules/js-run/lib/conn-imports-scan.mjs +0 -154
  169. package/rules/js-run/lib/docs/bunyan-imports.md +0 -121
  170. package/rules/js-run/lib/docs/check-env-scan.md +0 -438
  171. package/rules/js-run/lib/docs/conn-file-rules.md +0 -304
  172. package/rules/js-run/lib/docs/conn-imports-scan.md +0 -208
  173. package/rules/js-run/lib/docs/index.md +0 -16
  174. package/rules/js-run/lib/docs/promise-settimeout-scan.md +0 -334
  175. package/rules/js-run/lib/docs/temporal-scan.md +0 -29
  176. package/rules/js-run/lib/promise-settimeout-scan.mjs +0 -128
  177. package/rules/js-run/lib/temporal-scan.mjs +0 -52
  178. package/rules/js-run/main.json +0 -1
  179. package/rules/js-run/main.mdc +0 -16
  180. package/rules/js-run/package_json/concern.json +0 -9
  181. package/rules/js-run/package_json/package_json.mdc +0 -44
  182. package/rules/js-run/package_json/package_json.rego +0 -37
  183. package/rules/js-run/package_json/template/package.json.deny.json +0 -22
  184. package/rules/js-run/project-structure/concern.json +0 -3
  185. package/rules/js-run/project-structure/project-structure.mdc +0 -11
  186. package/rules/js-run/runtime/concern.json +0 -12
  187. package/rules/js-run/runtime/docs/fix-runtime.md +0 -27
  188. package/rules/js-run/runtime/docs/main.md +0 -35
  189. package/rules/js-run/runtime/fix-runtime.mjs +0 -46
  190. package/rules/js-run/runtime/main.mjs +0 -494
  191. package/rules/js-run/runtime/runtime.mdc +0 -184
  192. package/rules/js-run/scope/concern.json +0 -3
  193. package/rules/js-run/scope/scope.mdc +0 -11
  194. package/rules/npm-module/docs/index.md +0 -11
  195. package/rules/npm-module/emit_types_config/concern.json +0 -9
  196. package/rules/npm-module/emit_types_config/docs/fix-emit_types_config.md +0 -25
  197. package/rules/npm-module/emit_types_config/docs/index.md +0 -9
  198. package/rules/npm-module/emit_types_config/emit_types_config.mdc +0 -43
  199. package/rules/npm-module/emit_types_config/emit_types_config.rego +0 -28
  200. package/rules/npm-module/emit_types_config/fix-emit_types_config.mjs +0 -5
  201. package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +0 -9
  202. package/rules/npm-module/header_doc_pointer/concern.json +0 -5
  203. package/rules/npm-module/header_doc_pointer/docs/main.md +0 -40
  204. package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +0 -18
  205. package/rules/npm-module/header_doc_pointer/main.mjs +0 -131
  206. package/rules/npm-module/main.json +0 -1
  207. package/rules/npm-module/main.mdc +0 -36
  208. package/rules/npm-module/npm_package_json/concern.json +0 -9
  209. package/rules/npm-module/npm_package_json/docs/fix-npm_package_json.md +0 -27
  210. package/rules/npm-module/npm_package_json/docs/index.md +0 -9
  211. package/rules/npm-module/npm_package_json/fix-npm_package_json.mjs +0 -5
  212. package/rules/npm-module/npm_package_json/npm_package_json.mdc +0 -57
  213. package/rules/npm-module/npm_package_json/npm_package_json.rego +0 -73
  214. package/rules/npm-module/npm_package_json/template/package.json.snippet.json +0 -1
  215. package/rules/npm-module/package_structure/concern.json +0 -5
  216. package/rules/npm-module/package_structure/docs/main.md +0 -37
  217. package/rules/npm-module/package_structure/main.mjs +0 -515
  218. package/rules/npm-module/package_structure/package_structure.mdc +0 -63
  219. package/rules/npm-module/root_package_json/concern.json +0 -9
  220. package/rules/npm-module/root_package_json/docs/fix-root_package_json.md +0 -26
  221. package/rules/npm-module/root_package_json/docs/index.md +0 -9
  222. package/rules/npm-module/root_package_json/fix-root_package_json.mjs +0 -5
  223. package/rules/npm-module/root_package_json/root_package_json.mdc +0 -41
  224. package/rules/npm-module/root_package_json/root_package_json.rego +0 -28
  225. package/rules/npm-module/root_package_json/template/package.json.snippet.json +0 -1
  226. package/rules/npm-module/rule_meta/concern.json +0 -8
  227. package/rules/npm-module/rule_meta/docs/main.md +0 -35
  228. package/rules/npm-module/rule_meta/main.mjs +0 -119
  229. package/rules/npm-module/rule_meta/rule_meta.mdc +0 -11
  230. package/rules/npm-module/skill_meta/concern.json +0 -5
  231. package/rules/npm-module/skill_meta/docs/main.md +0 -149
  232. package/rules/npm-module/skill_meta/main.mjs +0 -91
  233. package/rules/npm-module/skill_meta/skill_meta.mdc +0 -11
  234. package/rules/tool-surface/docs/index.md +0 -11
  235. package/rules/tool-surface/main.json +0 -6
  236. package/rules/tool-surface/main.mdc +0 -72
  237. package/rules/vue/composition-api/composition-api.mdc +0 -82
  238. package/rules/vue/composition-api/concern.json +0 -3
  239. package/rules/vue/docs/index.md +0 -11
  240. package/rules/vue/lib/docs/index.md +0 -11
  241. package/rules/vue/lib/docs/vue-forbidden-imports.md +0 -265
  242. package/rules/vue/lib/vue-forbidden-imports.mjs +0 -264
  243. package/rules/vue/main.json +0 -1
  244. package/rules/vue/main.mdc +0 -18
  245. package/rules/vue/nheader-layout/concern.json +0 -3
  246. package/rules/vue/nheader-layout/nheader-layout.mdc +0 -171
  247. package/rules/vue/package_json/concern.json +0 -9
  248. package/rules/vue/package_json/package_json.mdc +0 -30
  249. package/rules/vue/package_json/package_json.rego +0 -140
  250. package/rules/vue/packages/concern.json +0 -6
  251. package/rules/vue/packages/docs/index.md +0 -11
  252. package/rules/vue/packages/docs/main.md +0 -35
  253. package/rules/vue/packages/main.mjs +0 -575
  254. package/rules/vue/packages/packages.mdc +0 -56
  255. package/rules/vue/quasar-ui/concern.json +0 -3
  256. package/rules/vue/quasar-ui/quasar-ui.mdc +0 -32
  257. package/rules/vue/structure/concern.json +0 -3
  258. package/rules/vue/structure/structure.mdc +0 -101
  259. package/rules/vue/testing/concern.json +0 -3
  260. package/rules/vue/testing/testing.mdc +0 -40
  261. package/rules/vue/tfm-translations/concern.json +0 -7
  262. package/rules/vue/tfm-translations/docs/main.md +0 -29
  263. package/rules/vue/tfm-translations/main.mjs +0 -55
  264. package/rules/vue/tfm-translations/tfm-translations.mdc +0 -32
  265. package/rules/vue/vite-config/concern.json +0 -3
  266. package/rules/vue/vite-config/vite-config.mdc +0 -153
  267. package/rules/vue/vite-env/concern.json +0 -3
  268. package/rules/vue/vite-env/vite-env.mdc +0 -61
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.28.1] - 2026-07-19
4
+
5
+ ### Fixed
6
+
7
+ - schemas/v8r-catalog: записи для knip-canonical.json (офіційна схема knip@5) і oxlint-canonical.json (any-заглушка) — прибирає «Could not find a schema» у v8r по data-файлах правила js/tooling
8
+
9
+ ## [1.28.0] - 2026-07-19
10
+
11
+ ### Changed
12
+
13
+ - lint: JS-сімʼя правил (js, bun, vue, js-run, js-bun-db, js-bun-redis, js-mssql, npm-module, tool-surface) переїхала з ядра у @7n/rules-lang-js (фаза 5c spec lang-plugins-extraction); ядро лишає рушій (auto-rules предикати, glob-to-regex і js-source-signals у scripts/lib — плагін імпортує їх назад через @7n/rules/scripts); залежності eslint/knip/jscpd/oxlint переїхали з ядра у плагін
14
+
3
15
  ## [1.27.0] - 2026-07-19
4
16
 
5
17
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules",
3
- "version": "1.27.0",
3
+ "version": "1.28.1",
4
4
  "description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
5
5
  "keywords": [
6
6
  "cli",
@@ -70,15 +70,11 @@
70
70
  "@zed-industries/agent-client-protocol": "^0.4.5",
71
71
  "ajv": "^8.20.0",
72
72
  "cli-progress": "^3.12.0",
73
- "eslint": "^10.4.1",
74
73
  "github-actionlint": "^1.7.12",
75
74
  "globby": "^16.0.0",
76
75
  "ignore": "^7.0.5",
77
- "jscpd": "^5.0.11",
78
- "knip": "^6.22.0",
79
76
  "markdownlint-cli2": "^0.22.1",
80
77
  "oxc-parser": "^0.137.0",
81
- "oxlint": "^1.68.0",
82
78
  "picomatch": "^4.0.4",
83
79
  "smol-toml": "^1.7.0",
84
80
  "v8r": "^6.1.0",
@@ -22,7 +22,8 @@
22
22
  "**/.licensee.json",
23
23
  "docs/specs/**/*.json",
24
24
  "docs/plans/**/*.json",
25
- "any.json"
25
+ "any.json",
26
+ "**/data/tooling/oxlint-canonical.json"
26
27
  ]
27
28
  },
28
29
  {
@@ -270,6 +271,14 @@
270
271
  "**/docs/layers.json",
271
272
  "layers.json"
272
273
  ]
274
+ },
275
+ {
276
+ "name": "knip-canonical.json",
277
+ "description": "Канонічний knip-конфіг правила js/tooling (@7n/rules-lang-js) — офіційна схема knip@5",
278
+ "url": "https://unpkg.com/knip@5/schema.json",
279
+ "fileMatch": [
280
+ "**/data/tooling/knip-canonical.json"
281
+ ]
273
282
  }
274
283
  ]
275
284
  }
@@ -23,14 +23,13 @@ import { fileURLToPath } from 'node:url'
23
23
  import { globby } from 'globby'
24
24
 
25
25
  import { ALWAYS_IGNORE } from './utils/walkDir.mjs'
26
- import { globToRegex } from '../rules/npm-module/package_structure/main.mjs'
27
- import { textHasBunSqlImport } from '../rules/js-bun-db/lib/bun-sql-scan.mjs'
26
+ import { globToRegex } from './lib/glob-to-regex.mjs'
27
+ import { textHasBunSqlImport, contentForVueImportScan } from './lib/js-source-signals.mjs'
28
28
  import {
29
29
  isGqlScanSourceFile,
30
30
  shouldSkipFileForGqlScan,
31
31
  sourceFileHasGqlTaggedTemplate
32
32
  } from '../rules/graphql/lib/graphql-gql-scan.mjs'
33
- import { contentForVueImportScan } from '../rules/vue/lib/vue-forbidden-imports.mjs'
34
33
  import { parseRuleAutoSpec, readRuleMetaRaw } from './lib/rule-meta.mjs'
35
34
  import { migrateRuleIds, normalizeIdList } from './lib/rule-meta-helpers.mjs'
36
35
  import { RULE_PREDICATES } from './lib/rule-predicates.mjs'
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: auto-rules.mjs
4
4
  resource: npm/scripts/auto-rules.mjs
5
5
  docgen:
6
- crc: d4a1b2da
6
+ crc: 5707eb47
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 90
9
9
  ---
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: JS Module
3
+ title: glob-to-regex.mjs
4
+ resource: npm/scripts/lib/glob-to-regex.mjs
5
+ docgen:
6
+ crc: 6c55d687
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ issues: judge:inaccurate:0.98
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ `globToRegex` перетворює glob-патерни на `RegExp`, щоб `auto-rules.mjs` міг зіставляти `main.json:auto.glob` зі зміненими файлами, а правило npm-module з `@7n/rules-lang-js` — перевіряти `files` у `package.json` тим самим способом. Це спільна основа для однакового тлумачення шляхових шаблонів у `main.json` і `package.json` без запису стану; конфіги, на які спирається код: `main.json`, `package.json`.
17
+
18
+ ## Поведінка
19
+
20
+ 1. `globToRegex` перетворює glob-патерн на `RegExp` з повними межами збігу, щоб один і той самий шаблон можна було застосовувати і до автодетекту змінених файлів, і до перевірок `files` у `package.json`.
21
+ 2. Вона трактує `**` як охоплення будь-якої кількості шляхових сегментів, `*` — як будь-яку послідовність символів у межах одного сегмента, `?` — як один символ у межах одного сегмента, а brace-альтернативи — як вибір одного з кількох варіантів.
22
+ 3. Вона зберігає літеральний зміст символів, які у регулярних виразах мають спеціальне значення, щоб шаблон поводився як glob, а не як довільний текстовий вираз.
23
+ 4. Вона повертає готовий шаблон для перевірки шляхів у бізнес-правилах, що читають `main.json` і `package.json`, не торкаючись файлової системи чи інших даних поза входом.
24
+
25
+ ## Публічний API
26
+
27
+ - globToRegex — Перетворює glob-патерни з `files` та `main.json:auto.glob` у `RegExp` з прив’язкою до початку й кінця рядка; підтримує `**`, `*`, `?` і `{a,b,c}` для варіантів, без `[…]`.
28
+
29
+ ## Гарантії поведінки
30
+
31
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -20,7 +20,9 @@ resource: npm/scripts/lib/
20
20
  | [ensure-tool.mjs](ensure-tool.md) | JS Module |
21
21
  | [generated-markdown.mjs](generated-markdown.md) | JS Module |
22
22
  | [gha-workflow.mjs](gha-workflow.md) | JS Module |
23
+ | [glob-to-regex.mjs](glob-to-regex.md) | JS Module |
23
24
  | [inline-template-links.mjs](inline-template-links.md) | JS Module |
25
+ | [js-source-signals.mjs](js-source-signals.md) | JS Module |
24
26
  | [list-project-rules-mdc.mjs](list-project-rules-mdc.md) | JS Module |
25
27
  | [list-rule-ids.mjs](list-rule-ids.md) | JS Module |
26
28
  | [load-cursor-config.mjs](load-cursor-config.md) | JS Module |
@@ -0,0 +1,32 @@
1
+ ---
2
+ type: JS Module
3
+ title: js-source-signals.mjs
4
+ resource: npm/scripts/lib/js-source-signals.mjs
5
+ docgen:
6
+ crc: 4a8d80d5
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ issues: judge:inaccurate:0.97
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ `auto-rules.mjs` викликає ці regex-only текстові сигнали на кожному зміненому файлі, без AST, щоб швидко збирати факти для авто-детекту правил у JS/TS/Vue-джерелах. Спільні функції `textHasBunSqlImport`, `extractVueScriptBlocks` і `contentForVueImportScan` живуть у `@7n/rules/scripts/lib/…` і використовуються також правилами `@7n/rules-lang-js` для `js-bun-db` та `vue`, щоб не дублювати одні й ті самі сигнали в різних місцях. Компонент read-only і не пише у ФС чи БД.
17
+
18
+ ## Поведінка
19
+
20
+ - `textHasBunSqlImport` — визначає, чи в тексті є імпорт `sql` або `SQL` з `bun`.
21
+ - `extractVueScriptBlocks` — витягує з Vue SFC увесь код із `<script>`-блоків і склеює його в один текст.
22
+ - `contentForVueImportScan` — готує вміст до сканування: для `.vue` лишає тільки `<script>`-блоки, для інших файлів бере весь текст.
23
+
24
+ ## Публічний API
25
+
26
+ - textHasBunSqlImport — знаходить у сирому тексті імпорт `sql` або `SQL` з `"bun"` для швидкого визначення, чи є в файлі доступ до Bun SQL API.
27
+ - extractVueScriptBlocks — дістає з Vue SFC лише вміст `<script>`, щоб аналіз не зачіпав template.
28
+ - contentForVueImportScan — для `.vue` бере тільки script-блоки, а для інших файлів — увесь текст, щоб сканувати саме релевантний код.
29
+
30
+ ## Гарантії поведінки
31
+
32
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Перетворення glob-патернів у RegExp — утиліт рушія авто-детекту правил
3
+ * (`auto-rules.mjs` матчить `main.json:auto.glob` по зміненим файлам) і
4
+ * перевірок `files` у package.json (правило npm-module з `@7n/rules-lang-js`).
5
+ * Живе в ядрі (фаза 5c spec lang-plugins-extraction): рушій не залежить від
6
+ * плагінів, а плагінні правила імпортують через `@7n/rules/scripts/lib/…`.
7
+ */
8
+
9
+ /** Символи зі спеціальним значенням у RegExp, які в glob — літерали (екрануємо). */
10
+ const REGEX_SPECIAL_IN_GLOB = new Set(['.', '+', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\'])
11
+
12
+ const GLOBSTAR_LEADING_RE = /^__GLOBSTAR__\//u
13
+ const GLOBSTAR_TRAILING_RE = /\/__GLOBSTAR__$/u
14
+
15
+ /**
16
+ * Перетворює glob-патерн (як у npm `files` чи `main.json:auto.glob`) у `RegExp`
17
+ * з якорями `^` / `$`. Підтримує globstar (нуль або більше сегментів), `*`
18
+ * (символи без `/`), `?` (один символ без `/`) і brace-альтернативи `{a,b,c}`
19
+ * (наприклад `*.{png,jpg,svg}` → `(?:png|jpg|svg)`). Клас `[…]` не
20
+ * підтримується — у негативних патернах `files` цього достатньо.
21
+ * @param {string} glob posix-шлях у glob-нотації
22
+ * @returns {RegExp} `RegExp` з якорями `^` / `$`
23
+ */
24
+ export function globToRegex(glob) {
25
+ const parts = glob.split('/')
26
+ const tokens = parts.map(p => {
27
+ if (p === '**') return '__GLOBSTAR__'
28
+ let out = ''
29
+ let braceDepth = 0
30
+ for (const c of p) {
31
+ switch (c) {
32
+ case '*': {
33
+ out += '[^/]*'
34
+ continue
35
+ }
36
+ case '?': {
37
+ out += '[^/]'
38
+ continue
39
+ }
40
+ case '{': {
41
+ out += '(?:'
42
+ braceDepth++
43
+ continue
44
+ }
45
+ case '}': {
46
+ if (braceDepth > 0) {
47
+ out += ')'
48
+ braceDepth--
49
+ continue
50
+ }
51
+ break
52
+ }
53
+ case ',': {
54
+ if (braceDepth > 0) {
55
+ out += '|'
56
+ continue
57
+ }
58
+ break
59
+ }
60
+ default: {
61
+ break
62
+ }
63
+ }
64
+ out += REGEX_SPECIAL_IN_GLOB.has(c) ? `\\${c}` : c
65
+ }
66
+ return out
67
+ })
68
+ let re = tokens.join('/')
69
+ re = re.replaceAll('/__GLOBSTAR__/', '(?:/.*/|/)')
70
+ re = re.replace(GLOBSTAR_LEADING_RE, '(?:.*/)?')
71
+ re = re.replace(GLOBSTAR_TRAILING_RE, '(?:/.*)?')
72
+ re = re.replaceAll('__GLOBSTAR__', '.*')
73
+ // Дозволено: уся функція існує саме для конструкції RegExp з glob-pattern
74
+ // (значення з package.json `files` або main.json `auto.glob`, не від
75
+ // кінцевого користувача), і спецсимволи вже екрановано через
76
+ // `REGEX_SPECIAL_IN_GLOB` вище.
77
+ // eslint-disable-next-line security/detect-non-literal-regexp
78
+ return new RegExp(`^${re}$`, 'u')
79
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Дешеві текстові сигнали JS/TS/Vue-джерел для збору фактів авто-детекту правил
3
+ * (`auto-rules.mjs` кличе їх на кожному зміненому файлі — без AST, лише regex).
4
+ * Живуть у ядрі (фаза 5c spec lang-plugins-extraction): рушій авто-детекту не
5
+ * імпортує код плагінів, а правила `@7n/rules-lang-js` (js-bun-db, vue)
6
+ * використовують ці ж функції через `@7n/rules/scripts/lib/…` — одне джерело
7
+ * правди без дублювання regex-ів.
8
+ */
9
+
10
+ const BUN_SQL_IMPORT_RE = /\bimport\s*\{[\s\S]*?\b(sql|SQL)\b[\s\S]*?\}\s*from\s*["']bun["']/u
11
+
12
+ /**
13
+ * Чи містить текст джерела імпорт імені `sql` або `SQL` з `"bun"`.
14
+ * Скан по сирому тексту — без AST, щоб бути дешевим: викликається на кожному
15
+ * JS/TS-файлі при зборі ознак для авто-детекту правил.
16
+ * @param {string} content вміст файлу
17
+ * @returns {boolean} true, якщо є імпорт sql або SQL з модуля bun
18
+ */
19
+ export function textHasBunSqlImport(content) {
20
+ return BUN_SQL_IMPORT_RE.test(content)
21
+ }
22
+
23
+ /**
24
+ * Витягує з SFC лише код усередині `<script>`, щоб не чіпати шаблон.
25
+ * @param {string} sfc вміст .vue файлу
26
+ * @returns {string} текст усередині тегів `<script>` (усі блоки поспіль)
27
+ */
28
+ export function extractVueScriptBlocks(sfc) {
29
+ const chunks = []
30
+ const re = /<script\b[^>]*>([\s\S]*?)<\/script>/gi
31
+ let m = re.exec(sfc)
32
+ while (m) {
33
+ chunks.push(m[1])
34
+ m = re.exec(sfc)
35
+ }
36
+ return chunks.join('\n\n')
37
+ }
38
+
39
+ /**
40
+ * Підбирає текст для сканування: для .vue — лише script-блоки, інакше — увесь вміст.
41
+ * @param {string} content сирий вміст файлу
42
+ * @param {string} filePath відносний шлях (для вибору режиму)
43
+ * @returns {string} текст для парсера/regex-сканів
44
+ */
45
+ export function contentForVueImportScan(content, filePath) {
46
+ if (filePath.endsWith('.vue')) {
47
+ return extractVueScriptBlocks(content)
48
+ }
49
+ return content
50
+ }
@@ -6,8 +6,8 @@
6
6
  * робота з `TemplateLiteral` (текст quasis, контекст SQL-списку).
7
7
  *
8
8
  * Використовується сканерами у `rules/<rule>/js/...` (наприклад,
9
- * `rules/js-bun-db/js/safety/bun-sql-scan.mjs`, `rules/js-mssql/js/deps/mssql-pool-scan.mjs`,
10
- * `rules/js-run/js/runtime/*-scan.mjs`) для уникнення дублювання boilerplate.
9
+ * `@7n/rules-lang-js`: rules/js-bun-db, rules/js-mssql, rules/js-run —
10
+ * фаза 5c spec lang-plugins-extraction) для уникнення дублювання boilerplate.
11
11
  */
12
12
  import { parseSync } from 'oxc-parser'
13
13
 
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: ast-scan-utils.mjs
4
4
  resource: npm/scripts/utils/ast-scan-utils.mjs
5
5
  docgen:
6
- crc: 0f9b4a21
6
+ crc: ed9f189b
7
7
  ---
8
8
 
9
9
  Цей файл містить утиліти для AST-сканерів JavaScript та TypeScript, що використовуються для аналізу коду та виявлення потенційних проблем. Він надає інструменти для обробки AST, перетворення даних та взаємодії з різними типами вузлів, забезпечуючи основу для створення правил безпеки та аналізу коду. Ці утиліти спрощують розробку сканерів, усуваючи необхідність повторного написання boilerplate-коду.
@@ -1,17 +0,0 @@
1
- ## Rego-gate: відповідність bunfig.toml канонічному шаблону
2
-
3
- Rego-пакет: `bun.bunfig`
4
-
5
- Цільовий файл: `bunfig.toml` (корінь репо).
6
-
7
- Шаблон (leaf-значення, які gate порівнює): [bunfig.toml.snippet.toml](./template/bunfig.toml.snippet.toml)
8
-
9
- Gate порівнює кожен leaf-ключ у кожній секції шаблону з фактичним значенням у `bunfig.toml`. Зайві ключі та секції — ігноруються. Deny-повідомлення виникає, якщо:
10
-
11
- - секція відсутня або не є обʼєктом (`bunfig.toml: відсутня секція [install]`)
12
- - leaf-ключ має інше значення (`bunfig.toml: у секції [install] має бути linker = "hoisted"`)
13
-
14
- ## Навіщо саме `linker = "hoisted"`
15
-
16
- Канонічна лінковка для кореневого `bunfig.toml` — **hoisted**: пласке `node_modules`,
17
- сумісне з інструментами, які не розуміють ізольований (isolated) layout Bun.
@@ -1,29 +0,0 @@
1
- # Перевірка `bunfig.toml` для bun (bun.mdc).
2
- #
3
- # Канон надходить через --data: { "template": { "snippet": ... } }
4
- # Структура --data сформована з template/bunfig.toml.snippet.toml.
5
- # Snippet — 2-рівнева мапа (section → key → expected). Walker такий самий,
6
- # як для ga.vscode_settings: leaf-by-leaf коли section-обʼєкт існує + окремий
7
- # deny коли section відсутній / не обʼєкт.
8
- package bun.bunfig
9
-
10
- import rego.v1
11
-
12
- # Leaf-by-leaf: section присутня й обʼєкт.
13
- deny contains msg if {
14
- some section, expected_inner in data.template.snippet
15
- inner := object.get(input, section, {})
16
- is_object(inner)
17
- some leaf_key, expected_value in expected_inner
18
- actual := object.get(inner, leaf_key, null)
19
- actual != expected_value
20
- msg := sprintf("bunfig.toml: у секції [%s] має бути %s = %q (bun.mdc)", [section, leaf_key, expected_value])
21
- }
22
-
23
- # Section відсутня (null) або не обʼєкт.
24
- deny contains msg if {
25
- some section in object.keys(data.template.snippet)
26
- raw := object.get(input, section, null)
27
- not is_object(raw)
28
- msg := sprintf("bunfig.toml: відсутня секція [%s] (bun.mdc)", [section])
29
- }
@@ -1,9 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "policy": {
5
- "files": {
6
- "single": "bunfig.toml"
7
- }
8
- }
9
- }
@@ -1,2 +0,0 @@
1
- [install]
2
- linker = "hoisted"
@@ -1,11 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/bun
4
- resource: npm/rules/bun/
5
- ---
6
-
7
- # npm/rules/bun
8
-
9
- | Файл | Тип |
10
- | ------------------- | --------- |
11
- | [main.mjs](main.md) | JS Module |
@@ -1,16 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": [
6
- "package-lock.json",
7
- "yarn.lock",
8
- "pnpm-lock.yaml",
9
- ".yarnrc.yml",
10
- ".yarn/**",
11
- "bun.lock",
12
- "bunfig.toml",
13
- "package.json"
14
- ]
15
- }
16
- }
@@ -1,29 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-layout.mjs
4
- resource: npm/rules/bun/layout/fix-layout.mjs
5
- docgen:
6
- crc: 14f58bce
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.98
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Т0-autofix паттерни для `bun/js/layout.mjs` забезпечують детерміноване виправлення структури проєкту. Він виконує такі дії, керуючись конфігом `package-lock.json`: видаляє заборонені файли (наприклад, `package-lock.json`, `yarn.lock`), створює відсутні конфігураційні файли (`bunfig.toml`) та каталоги (`.yarn`). Ці механізми реалізуються через публічну змінну `patterns` без звернення до LLM.
16
-
17
- ## Поведінка
18
-
19
- Поведінка:
20
-
21
- 1. Виконується детерміноване автоматичне виправлення структури проєкту на основі попереднього логу.
22
- 2. Перевіряється наявність заборонених файлів, таких як `package-lock.json`. У разі виявлення, ці файли фізично видаляються з робочої директорії.
23
- 3. Перевіряється наявність файлу `bunfig.toml`. Якщо він відсутній, його створюється з базовим налаштуванням для встановлення залежностей.
24
- 4. Перевіряється наявність каталогу `.yarn`. У разі його виявлення, цей каталог повністю видаляється.
25
- 5. Усі ці дії інкапсульовані у публічній змінній `patterns`, що містить набір визначених механізмів виправлення.
26
-
27
- ## Гарантії поведінки
28
-
29
- - (специфічних машинно-виведених гарантій немає)
@@ -1,34 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/bun/layout/main.mjs
5
- docgen:
6
- crc: 457e5fcd
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 95
9
- issues: anchor-miss:(bun.mdc),judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Цей модуль забезпечує автоматизовану перевірку конфігурації проекту, аналізуючи файли package.json та package-lock.json. Він діагностує відсутність ключових файлів або невідповідність усталеним стандартам управління залежностями. Успішна робота підтверджує відповідність проекту визначеним вимогам.
16
-
17
- ## Поведінка
18
-
19
- Поведінка:
20
-
21
- 1. При запуску `main` перевіряється наявність файлів блокування залежностей (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `.yarnrc.yml`). Якщо будь-який з них присутній, це розцінюється як порушення.
22
- 2. Перевіряється наявність директорії `.yarn`. Її наявність сприймається як порушення.
23
- 3. Перевіряється наявність файлу `bun.lock`. Якщо його немає, це вказує на необхідність виконання `bun i`.
24
- 4. Перевіряється наявність конфігураційного файлу `bunfig.toml`. Якщо його немає, це вимагає створення файлу з налаштуванням `[install] linker = "hoisted"` відповідно до вимог `bun.mdc`.
25
- 5. Визначається шлях до `package.json` у корені репозиторію. Якщо цей файл відсутній, процес перевірки зупиняється.
26
- 6. У разі успішної перевірки всіх умов, повертається код, що вказує на відсутність проблем.
27
-
28
- ## Публічний API
29
-
30
- main — перевіряє, чи відповідає проєкт встановленим у bun.mdc правилам.
31
-
32
- ## Гарантії поведінки
33
-
34
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,63 +0,0 @@
1
- /**
2
- * T0-autofix паттерни для `bun/layout` — детерміновані FS-виправлення
3
- * заборонених файлів (package-lock.json, yarn.lock тощо), відсутнього bunfig.toml
4
- * та каталогу .yarn без звернення до LLM.
5
- *
6
- * Unified lint surface: structured violations (test(violations)/apply(violations,ctx)).
7
- * Імена заборонених файлів читаються з `v.message`, не з агрегованого output-рядка.
8
- */
9
- import { existsSync, rmSync, writeFileSync } from 'node:fs'
10
- import { join } from 'node:path'
11
-
12
- const FORBIDDEN_FILE_RE = /Знайдено заборонений файл: \S+/u
13
- const FORBIDDEN_FILE_NAME_RE = /Знайдено заборонений файл: (\S+)/u
14
- const BUNFIG_MISSING_RE = /Відсутній bunfig\.toml/u
15
- const YARN_DIR_RE = /Знайдено директорію \.yarn/u
16
-
17
- /** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
18
- export const patterns = [
19
- {
20
- id: 'rm-forbidden-file',
21
- test: violations => violations.some(v => FORBIDDEN_FILE_RE.test(v.message)),
22
- apply: (violations, ctx) => {
23
- const cwd = ctx.cwd
24
- const touchedFiles = []
25
- for (const v of violations) {
26
- const m = FORBIDDEN_FILE_NAME_RE.exec(v.message)
27
- if (!m) continue
28
- const filePath = join(cwd, m[1])
29
- if (existsSync(filePath)) {
30
- ctx.recordWrite?.(filePath)
31
- rmSync(filePath, { force: true })
32
- touchedFiles.push(filePath)
33
- }
34
- }
35
- if (touchedFiles.length === 0) return { touchedFiles: [] }
36
- return { touchedFiles, message: `видалено: ${touchedFiles.join(', ')}` }
37
- }
38
- },
39
-
40
- {
41
- id: 'bun-bunfig-create',
42
- test: violations => violations.some(v => BUNFIG_MISSING_RE.test(v.message)),
43
- apply: (_violations, ctx) => {
44
- const target = join(ctx.cwd, 'bunfig.toml')
45
- if (existsSync(target)) return { touchedFiles: [] }
46
- ctx.recordWrite?.(target)
47
- writeFileSync(target, '[install]\nlinker = "hoisted"\n', 'utf8')
48
- return { touchedFiles: [target], message: 'створено bunfig.toml' }
49
- }
50
- },
51
-
52
- {
53
- id: 'bun-yarn-dir-remove',
54
- test: violations => violations.some(v => YARN_DIR_RE.test(v.message)),
55
- apply: (_violations, ctx) => {
56
- const target = join(ctx.cwd, '.yarn')
57
- if (!existsSync(target)) return { touchedFiles: [] }
58
- ctx.recordWrite?.(target)
59
- rmSync(target, { recursive: true, force: true })
60
- return { touchedFiles: [target], message: 'видалено .yarn/' }
61
- }
62
- }
63
- ]
@@ -1,60 +0,0 @@
1
- ## Структура lockfile та менеджер пакетів
2
-
3
- Проект використовує **тільки Bun** для керування залежностями та запуску скриптів.
4
-
5
- **Заборонені lockfile / директорії** (мають бути відсутні у репозиторії):
6
-
7
- - `package-lock.json`
8
- - `yarn.lock`
9
- - `pnpm-lock.yaml`
10
- - `.yarnrc.yml`
11
- - `.yarn/`
12
-
13
- Якщо якийсь із цих файлів чи директорій існує — **видали** його.
14
-
15
- **Обовʼязковий lockfile:** `bun.lock` (має бути присутній у корені).
16
-
17
- **Заборонені команди менеджерів пакетів:**
18
-
19
- - `npm install`, `yarn`, `pnpm` і їх відповідники lockfile (крім `bun.lock`)
20
-
21
- **Дозволені команди:**
22
-
23
- - `bun i`
24
- - `bun run <script>`
25
- - `bun add <pkg>`
26
- - `bun add -d <pkg>`
27
- - `bun remove <pkg>`
28
- - `bunx <tool>`
29
- - `npx <tool>` — якщо у проєкті вже використовується `npx` (не замінюй на `bunx`)
30
-
31
- **Одноразові CLI (`bunx` / `npx`):**
32
-
33
- - Якщо в проєкті вже використовується **`npx`** (скрипти, CI, Dockerfile) — **залишай `npx`**, не замінюй на `bunx`.
34
- - Якщо новий виклик CLI додається з нуля і в репозиторії прийнято лише Bun — можна `bunx <tool>`.
35
-
36
- **Не додавай** у `dependencies` / `devDependencies` пакети, які **використовуються лише як CLI** і їх достатньо викликати через **`bunx <pkg>`** (або **`npx`**, якщо в проєкті так прийнято): наприклад **oxlint**, **jscpd**, **eslint** у корені тощо. Виняток — пакет потрібен як **бібліотека** (імпорт у коді), peer для іншого пакета, або інструмент **не** покривається `bunx` у вашому CI.
37
-
38
- **Monorepo:**
39
-
40
- - Встановлювати залежності у відповідному пакеті, а не в корені без потреби.
41
- - Якщо залежність потрібна лише одному пакету, додавати її в директорії цього пакета.
42
- - У CI та локально запускати скрипти через `bun run`.
43
-
44
- **Dockerfile:**
45
-
46
- ```dockerfile
47
- FROM oven/bun:alpine AS build-env
48
- ```
49
-
50
- замість образу node.
51
-
52
- **GitHub Actions:** не вставляй у workflow окремі кроки **`actions/setup-node`**, **`oven-sh/setup-bun`**, **`actions/cache`** та **`bun install`** — їх **заборонено** дублювати в кожному job; завжди використовуй **локальний composite** (деталі й заборона дублювання — **ga.mdc**). Під капотом composite уже містить Node **24**, Bun, кеш і **`bun install --frozen-lockfile`**.
53
-
54
- Після **`actions/checkout@v6`** (`persist-credentials: false`):
55
-
56
- ```yaml
57
- - uses: ./.github/actions/setup-bun-deps
58
- ```
59
-
60
- Якщо в репозиторії action збережено під **`./npm/github-actions/setup-bun-deps`**, у `uses:` вкажи цей шлях замість `.github/actions/…` (**ga.mdc**).