@7n/rules 1.26.0 → 1.28.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 (292) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +2 -5
  3. package/rules/doc-files/docgen-crc/docs/main.md +1 -1
  4. package/rules/doc-files/docgen-crc/main.mjs +5 -12
  5. package/rules/doc-files/docgen-gen/docs/main.md +1 -1
  6. package/rules/doc-files/docgen-gen/main.mjs +12 -4
  7. package/rules/doc-files/docgen-scan/docs/main.md +2 -2
  8. package/rules/doc-files/docgen-scan/main.mjs +6 -13
  9. package/schemas/concern.json +4 -0
  10. package/scripts/auto-rules.mjs +2 -3
  11. package/scripts/docs/auto-rules.md +1 -1
  12. package/scripts/lib/concern-meta.mjs +14 -1
  13. package/scripts/lib/docs/concern-meta.md +3 -6
  14. package/scripts/lib/docs/glob-to-regex.md +31 -0
  15. package/scripts/lib/docs/index.md +2 -0
  16. package/scripts/lib/docs/js-source-signals.md +32 -0
  17. package/scripts/lib/glob-to-regex.mjs +79 -0
  18. package/scripts/lib/js-source-signals.mjs +50 -0
  19. package/scripts/lib/lint-surface/docs/ladder.md +3 -5
  20. package/scripts/lib/lint-surface/docs/run-fix.md +3 -2
  21. package/scripts/lib/lint-surface/ladder.mjs +18 -9
  22. package/scripts/lib/lint-surface/run-fix.mjs +15 -2
  23. package/scripts/utils/ast-scan-utils.mjs +2 -2
  24. package/scripts/utils/docs/ast-scan-utils.md +1 -1
  25. package/scripts/utils/docs/test-helpers.md +2 -1
  26. package/skills/doc-files/SKILL.md +1 -1
  27. package/skills/taze/js/docs/orchestrate.md +1 -1
  28. package/rules/bun/bunfig/bunfig.mdc +0 -17
  29. package/rules/bun/bunfig/bunfig.rego +0 -29
  30. package/rules/bun/bunfig/concern.json +0 -9
  31. package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +0 -2
  32. package/rules/bun/docs/index.md +0 -11
  33. package/rules/bun/layout/concern.json +0 -16
  34. package/rules/bun/layout/docs/fix-layout.md +0 -29
  35. package/rules/bun/layout/docs/main.md +0 -34
  36. package/rules/bun/layout/fix-layout.mjs +0 -63
  37. package/rules/bun/layout/layout.mdc +0 -60
  38. package/rules/bun/layout/main.mjs +0 -53
  39. package/rules/bun/licensee/concern.json +0 -7
  40. package/rules/bun/licensee/docs/fix-licensee.md +0 -27
  41. package/rules/bun/licensee/docs/index.md +0 -12
  42. package/rules/bun/licensee/docs/main.md +0 -30
  43. package/rules/bun/licensee/fix-licensee.mjs +0 -31
  44. package/rules/bun/licensee/main.mjs +0 -68
  45. package/rules/bun/lint-surface/concern.json +0 -3
  46. package/rules/bun/lint-surface/lint-surface.mdc +0 -13
  47. package/rules/bun/main.json +0 -1
  48. package/rules/bun/main.mdc +0 -11
  49. package/rules/bun/package_json/concern.json +0 -9
  50. package/rules/bun/package_json/docs/fix-package_json.md +0 -28
  51. package/rules/bun/package_json/docs/index.md +0 -9
  52. package/rules/bun/package_json/fix-package_json.mjs +0 -311
  53. package/rules/bun/package_json/package_json.mdc +0 -14
  54. package/rules/bun/package_json/package_json.rego +0 -64
  55. package/rules/bun/package_json/template/package.json.deny.json +0 -4
  56. package/rules/doc-files/docgen-extract/concern.json +0 -3
  57. package/rules/doc-files/docgen-extract/docs/main.md +0 -38
  58. package/rules/doc-files/docgen-extract/main.mjs +0 -275
  59. package/rules/doc-files/units/concern.json +0 -3
  60. package/rules/doc-files/units/docs/main.md +0 -31
  61. package/rules/doc-files/units/main.mjs +0 -19
  62. package/rules/doc-files/units-js/concern.json +0 -3
  63. package/rules/doc-files/units-js/docs/main.md +0 -32
  64. package/rules/doc-files/units-js/main.mjs +0 -141
  65. package/rules/js/check/check.mdc +0 -26
  66. package/rules/js/check/concern.json +0 -19
  67. package/rules/js/check/docs/eslint-config.md +0 -56
  68. package/rules/js/check/docs/fix-check.md +0 -48
  69. package/rules/js/check/docs/index.md +0 -13
  70. package/rules/js/check/docs/main.md +0 -48
  71. package/rules/js/check/eslint-config.mjs +0 -262
  72. package/rules/js/check/fix-check.mjs +0 -82
  73. package/rules/js/check/main.mjs +0 -310
  74. package/rules/js/dep-policy/concern.json +0 -4
  75. package/rules/js/dep-policy/dep-policy.mdc +0 -36
  76. package/rules/js/dep-policy/docs/main.md +0 -35
  77. package/rules/js/dep-policy/main.mjs +0 -99
  78. package/rules/js/docs/index.md +0 -11
  79. package/rules/js/eslint/concern.json +0 -7
  80. package/rules/js/eslint/docs/fix-eslint.md +0 -50
  81. package/rules/js/eslint/docs/fix-worker.md +0 -31
  82. package/rules/js/eslint/docs/index.md +0 -11
  83. package/rules/js/eslint/docs/main.md +0 -35
  84. package/rules/js/eslint/fix-eslint.mjs +0 -160
  85. package/rules/js/eslint/fix-worker.mjs +0 -139
  86. package/rules/js/eslint/main.mjs +0 -115
  87. package/rules/js/file-extensions/concern.json +0 -3
  88. package/rules/js/file-extensions/file-extensions.mdc +0 -12
  89. package/rules/js/jscpd_config/concern.json +0 -11
  90. package/rules/js/jscpd_config/docs/fix-jscpd_config.md +0 -26
  91. package/rules/js/jscpd_config/docs/index.md +0 -9
  92. package/rules/js/jscpd_config/fix-jscpd_config.mjs +0 -3
  93. package/rules/js/jscpd_config/jscpd_config.mdc +0 -42
  94. package/rules/js/jscpd_config/jscpd_config.rego +0 -44
  95. package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +0 -7
  96. package/rules/js/jscpd_duplicates/concern.json +0 -7
  97. package/rules/js/jscpd_duplicates/docs/main.md +0 -29
  98. package/rules/js/jscpd_duplicates/main.mjs +0 -69
  99. package/rules/js/knip/concern.json +0 -7
  100. package/rules/js/knip/docs/main.md +0 -32
  101. package/rules/js/knip/knip.mdc +0 -15
  102. package/rules/js/knip/main.mjs +0 -68
  103. package/rules/js/lint-findings/concern.json +0 -3
  104. package/rules/js/lint-findings/docs/main.md +0 -41
  105. package/rules/js/lint-findings/main.mjs +0 -125
  106. package/rules/js/main.json +0 -1
  107. package/rules/js/main.mdc +0 -18
  108. package/rules/js/package_json/concern.json +0 -9
  109. package/rules/js/package_json/docs/fix-package_json.md +0 -26
  110. package/rules/js/package_json/docs/index.md +0 -9
  111. package/rules/js/package_json/fix-package_json.mjs +0 -3
  112. package/rules/js/package_json/package_json.mdc +0 -15
  113. package/rules/js/package_json/package_json.rego +0 -142
  114. package/rules/js/package_json/template/package.json.snippet.json +0 -6
  115. package/rules/js/tooling/concern.json +0 -3
  116. package/rules/js/tooling/data/tooling/knip-canonical.json +0 -30
  117. package/rules/js/tooling/data/tooling/oxlint-canonical.json +0 -400
  118. package/rules/js/tooling/docs/main.md +0 -53
  119. package/rules/js/tooling/main.mjs +0 -183
  120. package/rules/js/utils_imports/concern.json +0 -4
  121. package/rules/js/utils_imports/docs/main.md +0 -50
  122. package/rules/js/utils_imports/main.mjs +0 -185
  123. package/rules/js/utils_imports/utils_imports.mdc +0 -15
  124. package/rules/js/vscode_extensions/concern.json +0 -11
  125. package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +0 -25
  126. package/rules/js/vscode_extensions/docs/index.md +0 -11
  127. package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +0 -1
  128. package/rules/js/vscode_extensions/template/extensions.json.snippet.json +0 -6
  129. package/rules/js/vscode_extensions/vscode_extensions.mdc +0 -11
  130. package/rules/js/vscode_extensions/vscode_extensions.rego +0 -12
  131. package/rules/js-bun-db/connection/concern.json +0 -3
  132. package/rules/js-bun-db/connection/connection.mdc +0 -42
  133. package/rules/js-bun-db/docs/index.md +0 -11
  134. package/rules/js-bun-db/lib/bun-sql-scan.mjs +0 -1055
  135. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +0 -63
  136. package/rules/js-bun-db/lib/docs/index.md +0 -11
  137. package/rules/js-bun-db/main.json +0 -1
  138. package/rules/js-bun-db/main.mdc +0 -8
  139. package/rules/js-bun-db/package_json/concern.json +0 -9
  140. package/rules/js-bun-db/package_json/package_json.mdc +0 -31
  141. package/rules/js-bun-db/package_json/package_json.rego +0 -15
  142. package/rules/js-bun-db/package_json/template/package.json.deny.json +0 -6
  143. package/rules/js-bun-db/pg_format_identifiers/concern.json +0 -3
  144. package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +0 -104
  145. package/rules/js-bun-db/safety/concern.json +0 -4
  146. package/rules/js-bun-db/safety/docs/main.md +0 -34
  147. package/rules/js-bun-db/safety/main.mjs +0 -430
  148. package/rules/js-bun-db/safety/safety.mdc +0 -458
  149. package/rules/js-bun-redis/docs/index.md +0 -11
  150. package/rules/js-bun-redis/imports/concern.json +0 -4
  151. package/rules/js-bun-redis/imports/docs/main.md +0 -36
  152. package/rules/js-bun-redis/imports/imports.mdc +0 -47
  153. package/rules/js-bun-redis/imports/main.mjs +0 -88
  154. package/rules/js-bun-redis/lib/docs/index.md +0 -11
  155. package/rules/js-bun-redis/lib/docs/redis-imports.md +0 -227
  156. package/rules/js-bun-redis/lib/redis-imports.mjs +0 -130
  157. package/rules/js-bun-redis/main.json +0 -1
  158. package/rules/js-bun-redis/main.mdc +0 -8
  159. package/rules/js-bun-redis/package_json/concern.json +0 -9
  160. package/rules/js-bun-redis/package_json/package_json.mdc +0 -11
  161. package/rules/js-bun-redis/package_json/package_json.rego +0 -15
  162. package/rules/js-bun-redis/package_json/template/package.json.deny.json +0 -12
  163. package/rules/js-mssql/deps/concern.json +0 -4
  164. package/rules/js-mssql/deps/docs/main.md +0 -33
  165. package/rules/js-mssql/deps/main.mjs +0 -297
  166. package/rules/js-mssql/docs/index.md +0 -11
  167. package/rules/js-mssql/lib/docs/index.md +0 -11
  168. package/rules/js-mssql/lib/docs/mssql-pool-scan.md +0 -380
  169. package/rules/js-mssql/lib/mssql-pool-scan.mjs +0 -610
  170. package/rules/js-mssql/main.json +0 -1
  171. package/rules/js-mssql/main.mdc +0 -144
  172. package/rules/js-mssql/mssql-tvp/concern.json +0 -3
  173. package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +0 -77
  174. package/rules/js-mssql/package_json/concern.json +0 -9
  175. package/rules/js-mssql/package_json/package_json.mdc +0 -9
  176. package/rules/js-mssql/package_json/package_json.rego +0 -57
  177. package/rules/js-run/configmap/concern.json +0 -9
  178. package/rules/js-run/configmap/configmap.mdc +0 -37
  179. package/rules/js-run/configmap/configmap.rego +0 -21
  180. package/rules/js-run/configmap/template/configmap.yaml.contains.yml +0 -4
  181. package/rules/js-run/docs/index.md +0 -11
  182. package/rules/js-run/jsconfig/concern.json +0 -9
  183. package/rules/js-run/jsconfig/docs/fix-jsconfig.md +0 -29
  184. package/rules/js-run/jsconfig/docs/index.md +0 -9
  185. package/rules/js-run/jsconfig/fix-jsconfig.mjs +0 -119
  186. package/rules/js-run/jsconfig/jsconfig.mdc +0 -48
  187. package/rules/js-run/jsconfig/jsconfig.rego +0 -59
  188. package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +0 -10
  189. package/rules/js-run/lib/bunyan-imports.mjs +0 -98
  190. package/rules/js-run/lib/check-env-scan.mjs +0 -338
  191. package/rules/js-run/lib/conn-file-rules.mjs +0 -214
  192. package/rules/js-run/lib/conn-imports-scan.mjs +0 -154
  193. package/rules/js-run/lib/docs/bunyan-imports.md +0 -121
  194. package/rules/js-run/lib/docs/check-env-scan.md +0 -438
  195. package/rules/js-run/lib/docs/conn-file-rules.md +0 -304
  196. package/rules/js-run/lib/docs/conn-imports-scan.md +0 -208
  197. package/rules/js-run/lib/docs/index.md +0 -16
  198. package/rules/js-run/lib/docs/promise-settimeout-scan.md +0 -334
  199. package/rules/js-run/lib/docs/temporal-scan.md +0 -29
  200. package/rules/js-run/lib/promise-settimeout-scan.mjs +0 -128
  201. package/rules/js-run/lib/temporal-scan.mjs +0 -52
  202. package/rules/js-run/main.json +0 -1
  203. package/rules/js-run/main.mdc +0 -16
  204. package/rules/js-run/package_json/concern.json +0 -9
  205. package/rules/js-run/package_json/package_json.mdc +0 -44
  206. package/rules/js-run/package_json/package_json.rego +0 -37
  207. package/rules/js-run/package_json/template/package.json.deny.json +0 -22
  208. package/rules/js-run/project-structure/concern.json +0 -3
  209. package/rules/js-run/project-structure/project-structure.mdc +0 -11
  210. package/rules/js-run/runtime/concern.json +0 -12
  211. package/rules/js-run/runtime/docs/fix-runtime.md +0 -27
  212. package/rules/js-run/runtime/docs/main.md +0 -35
  213. package/rules/js-run/runtime/fix-runtime.mjs +0 -46
  214. package/rules/js-run/runtime/main.mjs +0 -494
  215. package/rules/js-run/runtime/runtime.mdc +0 -184
  216. package/rules/js-run/scope/concern.json +0 -3
  217. package/rules/js-run/scope/scope.mdc +0 -11
  218. package/rules/npm-module/docs/index.md +0 -11
  219. package/rules/npm-module/emit_types_config/concern.json +0 -9
  220. package/rules/npm-module/emit_types_config/docs/fix-emit_types_config.md +0 -25
  221. package/rules/npm-module/emit_types_config/docs/index.md +0 -9
  222. package/rules/npm-module/emit_types_config/emit_types_config.mdc +0 -43
  223. package/rules/npm-module/emit_types_config/emit_types_config.rego +0 -28
  224. package/rules/npm-module/emit_types_config/fix-emit_types_config.mjs +0 -5
  225. package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +0 -9
  226. package/rules/npm-module/header_doc_pointer/concern.json +0 -5
  227. package/rules/npm-module/header_doc_pointer/docs/main.md +0 -40
  228. package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +0 -18
  229. package/rules/npm-module/header_doc_pointer/main.mjs +0 -131
  230. package/rules/npm-module/main.json +0 -1
  231. package/rules/npm-module/main.mdc +0 -36
  232. package/rules/npm-module/npm_package_json/concern.json +0 -9
  233. package/rules/npm-module/npm_package_json/docs/fix-npm_package_json.md +0 -27
  234. package/rules/npm-module/npm_package_json/docs/index.md +0 -9
  235. package/rules/npm-module/npm_package_json/fix-npm_package_json.mjs +0 -5
  236. package/rules/npm-module/npm_package_json/npm_package_json.mdc +0 -57
  237. package/rules/npm-module/npm_package_json/npm_package_json.rego +0 -73
  238. package/rules/npm-module/npm_package_json/template/package.json.snippet.json +0 -1
  239. package/rules/npm-module/package_structure/concern.json +0 -5
  240. package/rules/npm-module/package_structure/docs/main.md +0 -37
  241. package/rules/npm-module/package_structure/main.mjs +0 -515
  242. package/rules/npm-module/package_structure/package_structure.mdc +0 -63
  243. package/rules/npm-module/root_package_json/concern.json +0 -9
  244. package/rules/npm-module/root_package_json/docs/fix-root_package_json.md +0 -26
  245. package/rules/npm-module/root_package_json/docs/index.md +0 -9
  246. package/rules/npm-module/root_package_json/fix-root_package_json.mjs +0 -5
  247. package/rules/npm-module/root_package_json/root_package_json.mdc +0 -41
  248. package/rules/npm-module/root_package_json/root_package_json.rego +0 -28
  249. package/rules/npm-module/root_package_json/template/package.json.snippet.json +0 -1
  250. package/rules/npm-module/rule_meta/concern.json +0 -8
  251. package/rules/npm-module/rule_meta/docs/main.md +0 -35
  252. package/rules/npm-module/rule_meta/main.mjs +0 -119
  253. package/rules/npm-module/rule_meta/rule_meta.mdc +0 -11
  254. package/rules/npm-module/skill_meta/concern.json +0 -5
  255. package/rules/npm-module/skill_meta/docs/main.md +0 -149
  256. package/rules/npm-module/skill_meta/main.mjs +0 -91
  257. package/rules/npm-module/skill_meta/skill_meta.mdc +0 -11
  258. package/rules/tool-surface/docs/index.md +0 -11
  259. package/rules/tool-surface/main.json +0 -6
  260. package/rules/tool-surface/main.mdc +0 -72
  261. package/rules/vue/composition-api/composition-api.mdc +0 -82
  262. package/rules/vue/composition-api/concern.json +0 -3
  263. package/rules/vue/docs/index.md +0 -11
  264. package/rules/vue/lib/docs/index.md +0 -11
  265. package/rules/vue/lib/docs/vue-forbidden-imports.md +0 -265
  266. package/rules/vue/lib/vue-forbidden-imports.mjs +0 -264
  267. package/rules/vue/main.json +0 -1
  268. package/rules/vue/main.mdc +0 -18
  269. package/rules/vue/nheader-layout/concern.json +0 -3
  270. package/rules/vue/nheader-layout/nheader-layout.mdc +0 -171
  271. package/rules/vue/package_json/concern.json +0 -9
  272. package/rules/vue/package_json/package_json.mdc +0 -30
  273. package/rules/vue/package_json/package_json.rego +0 -140
  274. package/rules/vue/packages/concern.json +0 -6
  275. package/rules/vue/packages/docs/index.md +0 -11
  276. package/rules/vue/packages/docs/main.md +0 -35
  277. package/rules/vue/packages/main.mjs +0 -575
  278. package/rules/vue/packages/packages.mdc +0 -56
  279. package/rules/vue/quasar-ui/concern.json +0 -3
  280. package/rules/vue/quasar-ui/quasar-ui.mdc +0 -32
  281. package/rules/vue/structure/concern.json +0 -3
  282. package/rules/vue/structure/structure.mdc +0 -101
  283. package/rules/vue/testing/concern.json +0 -3
  284. package/rules/vue/testing/testing.mdc +0 -40
  285. package/rules/vue/tfm-translations/concern.json +0 -7
  286. package/rules/vue/tfm-translations/docs/main.md +0 -29
  287. package/rules/vue/tfm-translations/main.mjs +0 -55
  288. package/rules/vue/tfm-translations/tfm-translations.mdc +0 -32
  289. package/rules/vue/vite-config/concern.json +0 -3
  290. package/rules/vue/vite-config/vite-config.mdc +0 -153
  291. package/rules/vue/vite-env/concern.json +0 -3
  292. package/rules/vue/vite-env/vite-env.mdc +0 -61
@@ -1,275 +0,0 @@
1
- /** @see ./docs/docgen-extract.md */
2
-
3
- import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
4
- import { readFileSync } from 'node:fs'
5
-
6
- const BUILTIN_MODULES = new Set([
7
- 'fs',
8
- 'path',
9
- 'crypto',
10
- 'os',
11
- 'util',
12
- 'stream',
13
- 'events',
14
- 'http',
15
- 'https',
16
- 'url',
17
- 'child_process',
18
- 'process',
19
- 'assert',
20
- 'buffer',
21
- 'zlib',
22
- 'readline'
23
- ])
24
-
25
- const JSDOC_OPEN_RE = /^\s*\/\*\*?/
26
- const JSDOC_CLOSE_RE = /\*\/\s*$/
27
- const STAR_PREFIX_RE = /^\s*\*?\s?/
28
- const PARAM_LINE_RE = /^@param[ \t]{1,8}(?:\{[^}]{0,200}\}[ \t]{1,8})?\[?([\w.]{1,80})\]?[ \t]{0,8}(.{0,400})$/
29
- const RETURNS_LINE_RE = /^@returns?[ \t]{1,8}(?:\{[^}]{0,200}\}[ \t]{1,8})?(.{0,400})$/
30
- const FILE_HEADER_RE = /^\s*\/\*\*([\s\S]*?)\*\//
31
- const PRECEDING_JSDOC_RE = /\/\*\*(?:(?!\*\/)[\s\S])*\*\/\s*$/
32
- const EXPORT_DECL_RE = /export\s+(?:async\s+)?(function|const|class)\s+(\w+)/g
33
- // Top-level function/class декларації (колонка 0) — для R6: службові функції,
34
- // які не експортуються, не мають протікати у Поведінку/API як «публічні».
35
- const TOP_FN_DECL_RE = /^(?:export\s+)?(?:default\s+)?(?:async\s+)?(?:function\*?|class)\s+(\w+)/gm
36
- const IMPORT_FROM_RE = /^import[ \t]{1,8}[\s\S]{0,300}?from\s{1,8}['"]([^'"]+)['"]/gm
37
- const NODE_PREFIX_RE = /^node:/
38
- const INTERNAL_IMPORT_RE = /import[ \t]{1,8}([^'"]{0,300}?)from[ \t]{1,8}['"]\.[^'"]{1,300}['"]/g
39
- const NAMED_BRACES_RE = /\{([^}]{1,400})\}/
40
- const IDENT_RE = /^[\w$]{1,80}$/
41
- const IMPORT_AS_RE = /[ \t]{1,8}as[ \t]{1,8}.{0,200}/
42
- const WRITE_FS_RE = /\b(writeFile|mkdir|rmdir|unlink|appendFile|createWriteStream|rm\()/
43
- const CATCH_RE = /catch\s*\(/
44
- const TRY_RE = /\btry\s*\{/
45
- // Falsy-return як «fail-safe» — лише коли воно в catch/error-гілці (інакше це
46
- // звичайний guard `if (!x) return null`, не обробка помилки). Уникає over-claim.
47
- const FALSY_RETURN_RE = /catch[\s\S]{0,400}?return\s+(false|null|''|"")/
48
- // Мережа: окрім явного fetch/http, ловимо абстраговані клієнти (graphql/db/rpc/
49
- // octokit/.request/.query). Хибний false-negative тут = небезпечна гарантія
50
- // «без мережі», тож свідомо схиляємось до over-detection (м'якший бік помилки).
51
- const NETWORK_RE =
52
- /\bfetch\(|https?:\/\/|\bhttps?\.|axios|\bgot\(|graphql|\.request\(|\.query\(|\.mutate\(|octokit|node-fetch|undici|\bgrpc\b|websocket/i
53
- // Будь-який `throw` назовні → НЕ можна гарантувати «fail-safe / без винятків».
54
- const THROW_RE = /\bthrow\s/
55
- // Запис у БД / зовнішню мутацію → НЕ read-only (навіть якщо нема ФС-запису).
56
- // Розбито на кілька простіших патернів (та сама семантика через OR у `isMutation`),
57
- // щоб уникнути надмірної складності одного великого regex.
58
- const MUTATION_CALL_RE = /\b(insert|update|delete|upsert|drop|destroy|save)[A-Za-z]*\s*[(,]/
59
- const MUTATION_NAME_RE = /[Mm]utation\b|\bmut[A-Z]\w*/
60
- const MUTATION_METHOD_RE = /\.(save|create|update|delete|insert|destroy|mutate)\(/
61
- // Raw-SQL tagged-template виклики (напр. `pgWrite\`UPDATE ...\``) — DML-ключове
62
- // слово стоїть на початку тіла шаблону, не перед `(`, тож JS-орієнтовані
63
- // патерни вище його не ловлять. Сигнал мінімальний, але навмисний: тег-функція
64
- // (ідентифікатор впритул перед `` ` ``) + DML-keyword одразу після відкриття —
65
- // уникає false positive на звичайних рядках/коментарях, де немає теg-виклику.
66
- const SQL_TAGGED_MUTATION_RE = /\b\w+`\s*(?:UPDATE|INSERT|MERGE\s+INTO|DELETE\s+FROM|UPSERT)\b/i
67
- /**
68
- * @param {string} src вміст файлу
69
- * @returns {boolean} чи є ознаки мутації БД / зовнішнього стану
70
- */
71
- const isMutation = src =>
72
- MUTATION_CALL_RE.test(src) ||
73
- MUTATION_NAME_RE.test(src) ||
74
- MUTATION_METHOD_RE.test(src) ||
75
- SQL_TAGGED_MUTATION_RE.test(src)
76
- // Кеш — лише за ІМЕНОВАНИМ маркером (`cache`/`Cache`/`memoize`), не за будь-яким
77
- // `new Map()`: акумулятор (напр. `byPath = new Map()`) — не кеш, а хибна гарантія
78
- // «Кешує результати» гірша за пропуск (фабрикація > мовчання).
79
- const CACHE_RE = /cache|memoi[sz]e/i
80
-
81
- /**
82
- * Прибирає `/** *​/`-обрамлення й `*`-префікси, повертає чистий текст рядками.
83
- * @param {string} raw сирий JSDoc-блок з обрамленням
84
- * @returns {string} очищений текст без обрамлення й префіксів
85
- */
86
- function cleanJsDoc(raw) {
87
- return raw
88
- .replace(JSDOC_OPEN_RE, '')
89
- .replace(JSDOC_CLOSE_RE, '')
90
- .split('\n')
91
- .map(l => l.replace(STAR_PREFIX_RE, '').trimEnd())
92
- .join('\n')
93
- .trim()
94
- }
95
-
96
- /**
97
- * Опис (без @-тегів) + параметри з `@param` як «name — опис».
98
- * @param {string} raw сирий JSDoc-блок
99
- * @returns {{desc:string, params:Array<{name:string, desc:string}>, ret:string}} розпарсений опис, параметри й опис повернення
100
- */
101
- function parseJsDoc(raw) {
102
- const text = cleanJsDoc(raw)
103
- const lines = text.split('\n')
104
- const descLines = []
105
- const params = []
106
- let ret = ''
107
- for (const l of lines) {
108
- const pm = l.match(PARAM_LINE_RE)
109
- if (pm) {
110
- const desc = pm[2].trim()
111
- // «опис.» — JSDoc-заглушка без сенсу; не тягнемо її як факт
112
- params.push({ name: pm[1], desc: desc === 'опис.' ? '' : desc })
113
- continue
114
- }
115
- const rm = l.match(RETURNS_LINE_RE)
116
- if (rm) {
117
- ret = rm[1].trim()
118
- continue
119
- }
120
- if (l.startsWith('@')) continue
121
- descLines.push(l)
122
- }
123
- return { desc: descLines.join('\n').trim(), params, ret }
124
- }
125
-
126
- /**
127
- * Провідний блок-коментар файлу (намір), якщо він перед першим import/кодом.
128
- * @param {string} src вміст файлу
129
- * @returns {string} текст header-коментаря або порожній рядок
130
- */
131
- function extractFileHeader(src) {
132
- const m = src.match(FILE_HEADER_RE)
133
- if (!m) return ''
134
- // має бути на самому початку (до import/код)
135
- if (src.slice(0, m.index).trim() !== '') return ''
136
- return parseJsDoc(m[0]).desc
137
- }
138
-
139
- /**
140
- * Блок-коментар, що стоїть ВПРИТУЛ перед позицією (лише пробіли між ними).
141
- * `(?:(?!\*​/)[\s\S])*` гарантує, що тіло не містить `*​/`, тож захоплюється рівно один
142
- * найближчий блок — без жадібного «перестрибування» через імпорти/код.
143
- * @param {string} prefix вміст файлу до позиції експорту
144
- * @returns {string|null} JSDoc-блок або null якщо немає
145
- */
146
- function precedingJsDoc(prefix) {
147
- const m = prefix.match(PRECEDING_JSDOC_RE)
148
- return m ? m[0] : null
149
- }
150
-
151
- /**
152
- * Експорти + JSDoc, що безпосередньо передує кожному.
153
- * @param {string} src вміст файлу
154
- * @returns {Array<object>} список експортів із метаданими
155
- */
156
- function extractExports(src) {
157
- const out = []
158
- for (const m of src.matchAll(EXPORT_DECL_RE)) {
159
- const [, kind, name] = m
160
- const jsdocRaw = precedingJsDoc(src.slice(0, m.index))
161
- out.push({ name, kind, ...(jsdocRaw ? parseJsDoc(jsdocRaw) : { desc: '', params: [], ret: '' }) })
162
- }
163
- return out
164
- }
165
-
166
- /**
167
- * Імпорти, класифіковані на stdlib / npm / internal.
168
- * @param {string} src вміст файлу
169
- * @returns {{stdlib:Array<string>, npm:Array<string>, internal:Array<string>}} розкласифіковані шляхи імпортів
170
- */
171
- function extractImports(src) {
172
- const internal = new Set(),
173
- npm = new Set(),
174
- stdlib = new Set()
175
- for (const m of src.matchAll(IMPORT_FROM_RE)) {
176
- const s = m[1]
177
- if (s.startsWith('node:') || BUILTIN_MODULES.has(s.split('/', 1)[0])) stdlib.add(s.replace(NODE_PREFIX_RE, ''))
178
- else if (s.startsWith('.') || s.startsWith('/')) internal.add(s)
179
- else npm.add(s)
180
- }
181
- return { stdlib: [...stdlib], npm: [...npm], internal: [...internal] }
182
- }
183
-
184
- /**
185
- * Імена символів, імпортованих із внутрішніх модулів — їх модель не має згадувати.
186
- * @param {string} src вміст файлу
187
- * @returns {Array<string>} список імен внутрішніх символів
188
- */
189
- function extractInternalSymbols(src) {
190
- const out = new Set()
191
- for (const m of src.matchAll(INTERNAL_IMPORT_RE)) {
192
- const clause = m[1]
193
- const named = clause.match(NAMED_BRACES_RE)
194
- if (named) {
195
- for (const n of named[1].split(',')) {
196
- const name = n.replace(IMPORT_AS_RE, '').trim()
197
- if (name) out.add(name)
198
- }
199
- }
200
- const defName = clause.replace(NAMED_BRACES_RE, '').replaceAll(',', ' ').trim().split(' ', 1)[0]
201
- if (defName && IDENT_RE.test(defName)) out.add(defName)
202
- }
203
- return [...out]
204
- }
205
-
206
- /**
207
- * Імена top-level функцій/класів, які НЕ експортуються (службові помічники).
208
- * Модель не має подавати їх як «публічні функції» у Поведінці/API (R6).
209
- * Const-стрілки свідомо не ловимо — менше false-positive на змістовних константах.
210
- * @param {string} src вміст файлу
211
- * @returns {Array<string>} список імен неекспортованих функцій/класів
212
- */
213
- function extractLocalSymbols(src) {
214
- const exported = new Set(Array.from(src.matchAll(EXPORT_DECL_RE), m => m[2]))
215
- const out = new Set()
216
- for (const m of src.matchAll(TOP_FN_DECL_RE)) {
217
- if (!exported.has(m[1])) out.add(m[1])
218
- }
219
- return [...out]
220
- }
221
-
222
- /**
223
- * Поведінкові маркери — евристики регулярками.
224
- * @param {string} src вміст файлу
225
- * @returns {object} набір прапорців-евристик
226
- */
227
- function extractMarkers(src) {
228
- // помітні «пропуски»: dir/segment-літерали у фільтрах
229
- const skips = new Set()
230
- for (const lit of ['.github', '.git', 'node_modules', 'base/', 'ua/', '.firebase']) {
231
- if (src.includes(`'${lit}`) || src.includes(`"${lit}`) || src.includes(`/${lit}`)) skips.add(lit)
232
- }
233
- return {
234
- // «Фабрикація > мовчання»: прапорець true лише за high-confidence; інакше
235
- // guaranteesFromMarkers/factsSummary його ОПУСКАЮТЬ (не стверджують протилежне).
236
- readOnly: !WRITE_FS_RE.test(src) && !isMutation(src), // ні ФС-запису, ні DB-мутацій
237
- catchesErrors: (CATCH_RE.test(src) || TRY_RE.test(src)) && !THROW_RE.test(src), // fail-safe лише якщо НЕ кидає
238
- returnsFalsyOnFail: FALSY_RETURN_RE.test(src) && !THROW_RE.test(src),
239
- network: NETWORK_RE.test(src),
240
- caches: CACHE_RE.test(src),
241
- skips: [...skips]
242
- }
243
- }
244
- /**
245
- * Головний екстрактор: код файлу → факт-лист.
246
- * @param {string} src вміст файлу
247
- * @param {string} relPath шлях (для контексту/мови екстрактора)
248
- * @returns {{relPath:string, lang:string, header:string, exports:Array, imports:object, markers:object}} структура фактів про файл
249
- */
250
- export function extractFacts(src, relPath) {
251
- const lang = relPath.split('.').pop()
252
- if (!['js', 'mjs', 'ts'].includes(lang)) {
253
- return { relPath, lang, unsupported: true, header: '', exports: [], imports: {}, markers: {} }
254
- }
255
- return {
256
- relPath,
257
- lang,
258
- header: extractFileHeader(src),
259
- exports: extractExports(src),
260
- imports: extractImports(src),
261
- internalSymbols: extractInternalSymbols(src),
262
- localSymbols: extractLocalSymbols(src),
263
- markers: extractMarkers(src)
264
- }
265
- }
266
-
267
- // CLI для інспекції: node docgen-extract.mjs <file>
268
- if (isRunAsCli(import.meta.url)) {
269
- const file = process.argv[2]
270
- if (!file) {
271
- throw new Error('Usage: node docgen-extract.mjs <file>')
272
- }
273
- const facts = extractFacts(readFileSync(file, 'utf8'), file)
274
- console.log(JSON.stringify(facts, null, 2))
275
- }
@@ -1,3 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json"
3
- }
@@ -1,31 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/doc-files/units/main.mjs
5
- docgen:
6
- crc: 8acdefc1
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
- Цей файл забезпечує аналіз вмісту файлів різного мовного формату для вилучення інформації про юніти. Він обробляє вміст, визначаючи відповідний метод вилучення для JavaScript-подібних або Rust-файлів. Публічна функція `extractUnits` виконує механізм вилучення юнітних даних з коду.
16
-
17
- ## Поведінка
18
-
19
- 1. Метод `extractUnits` приймає вміст файлу та його відносний шлях.
20
- 2. Визначається розширення файлу за його відносним шляхом.
21
- 3. Якщо розширення відповідає JavaScript-подібним мовам (js, mjs, ts, jsx, tsx, cts, mts), викликається відповідна функція для вилучення юнітів на основі AST.
22
- 4. Якщо розширення 'rs', викликається відповідна функція для вилучення юнітів шляхом парсингу за допомогою регулярних виразів та підрахунку блоків.
23
- 5. Якщо розширення не підтримується або файл не може бути проаналізований, метод повертає null.
24
-
25
- ## Публічний API
26
-
27
- - extractUnits — Витягує одиниці виміру, визначаючи метод аналізу на основі розширення файлу (від AST для JS/TS до простого пошуку для Vue/Py).
28
-
29
- ## Гарантії поведінки
30
-
31
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,19 +0,0 @@
1
- /** @see ./docs/units.md */
2
-
3
- import { extractUnitsJs } from '../units-js/main.mjs'
4
-
5
- const JS_EXT = new Set(['js', 'mjs', 'ts', 'jsx', 'tsx', 'cts', 'mts'])
6
-
7
- /**
8
- * Мовно-агностичний фасад юніт-шару. Диспатчить за розширенням:
9
- * js/mjs/ts → oxc AST; інші мови (rs — lang-плагін, extension-point
10
- * `doc-files`.extractUnits; vue/py) → null (whole-file шлях).
11
- * @param {string} src вміст файлу
12
- * @param {string} relPath шлях файлу
13
- * @returns {Array<object>|null} юніти або null, якщо мова ще не підтримана / файл не парситься
14
- */
15
- export function extractUnits(src, relPath) {
16
- const ext = (relPath.split('.').pop() || '').toLowerCase()
17
- if (JS_EXT.has(ext)) return extractUnitsJs(src, relPath)
18
- return null
19
- }
@@ -1,3 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json"
3
- }
@@ -1,32 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/doc-files/units-js/main.mjs
5
- docgen:
6
- crc: 395188f4
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Будь ласка, надайте секцію «overview», яку необхідно переписати.
16
-
17
- ## Поведінка
18
-
19
- 1. Функція extractUnitsJs аналізує вміст файлу, щоб виявити ідентифіковані юніти (функції, класи, const-функції).
20
- 2. Вона визначає, які юніти є експортованими та обробляє їх для включення до списку.
21
- 3. Для кожного знайденого юніту вона витягує відповідний опис з JSDoc, що передує його оголошенню.
22
- 4. Зібрана інформація про юніт включає його назву, тип (функція, клас, const), прапор експорту, діапазон у вихідному коді та повний вихідний код.
23
- 5. Система виявляє всі виклики інших юнітів у тілі коду кожного юніта.
24
- 6. В результаті повертається список об'єктів, де кожен об'єкт описує один юніт, і в якому вказано лише посилання на інші виявлені юніти.
25
-
26
- ## Публічний API
27
-
28
- extractUnitsJs — знаходить та витягує на верхньому рівні логічні блоки (функції/класи/константи) з файлів JavaScript/TypeScript, які є частиною юніт-шару. Включає інформацію про експорт та взаємодії з іншими юнітами.
29
-
30
- ## Гарантії поведінки
31
-
32
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,141 +0,0 @@
1
- /** @see ./docs/units-js.md */
2
-
3
- import { parseProgramOrNull, walkAstWithAncestors } from '../../../scripts/utils/ast-scan-utils.mjs'
4
-
5
- // JSDoc-блок, що стоїть впритул перед позицією (лише пробіли між ними).
6
- const JSDOC_BEFORE_RE = /\/\*\*(?:(?!\*\/)[\s\S])*\*\/\s*$/
7
- const JSDOC_OPEN_RE = /^\s*\/\*\*?/
8
- const JSDOC_CLOSE_RE = /\*\/\s*$/
9
- const STAR_PREFIX_RE = /^\s*\*?\s?/
10
-
11
- /**
12
- * Очищає JSDoc від обрамлення `/** *​/` і `*`-префіксів.
13
- * @param {string} raw сирий блок або порожній рядок
14
- * @returns {string} текст опису без тегів-обрамлення
15
- */
16
- function cleanDoc(raw) {
17
- if (!raw) return ''
18
- return raw
19
- .replace(JSDOC_OPEN_RE, '')
20
- .replace(JSDOC_CLOSE_RE, '')
21
- .split('\n')
22
- .map(l => l.replace(STAR_PREFIX_RE, '').trimEnd())
23
- .join('\n')
24
- .trim()
25
- }
26
-
27
- /**
28
- * JSDoc, що передує позиції `start` у джерелі (або порожній рядок).
29
- * @param {string} src вміст файлу
30
- * @param {number} start зміщення початку декларації
31
- * @returns {string} очищений опис
32
- */
33
- function precedingDoc(src, start) {
34
- const m = src.slice(0, start).match(JSDOC_BEFORE_RE)
35
- return cleanDoc(m ? m[0] : '')
36
- }
37
-
38
- /**
39
- * Імʼя функції, що викликається (проста Identifier або `obj.method`).
40
- * @param {Record<string, unknown>} node CallExpression
41
- * @returns {string|null} імʼя callee або null
42
- */
43
- function calleeName(node) {
44
- const c = node.callee
45
- if (!c || typeof c !== 'object') return null
46
- if (c.type === 'Identifier') return c.name
47
- if (c.type === 'MemberExpression' && !c.computed && c.property?.type === 'Identifier') return c.property.name
48
- return null
49
- }
50
-
51
- /**
52
- * Множина імен, що викликаються у тілі вузла (сирі callee — фільтрація на ребра
53
- * call-graph робиться у `extractUnitsJs` після збору всіх імен юнітів).
54
- * @param {unknown} node AST-вузол юніта
55
- * @returns {Set<string>} імена викликів
56
- */
57
- function collectCalls(node) {
58
- const names = new Set()
59
- walkAstWithAncestors(node, [], n => {
60
- if (n.type !== 'CallExpression') {
61
- return
62
- }
63
-
64
- const name = calleeName(n)
65
- if (name) names.add(name)
66
- })
67
- return names
68
- }
69
-
70
- /**
71
- * Будує юніт із декларації, додає у `units`. Розпізнає function/class та
72
- * const-функції (`const x = () => {}` / `function expression`).
73
- * @param {Record<string, unknown>} decl декларація (function/class/variable)
74
- * @param {boolean} exported чи експортується
75
- * @param {number} docStart зміщення для пошуку JSDoc (зовнішній export-вузол)
76
- * @param {string} src вміст файлу
77
- * @param {Array<object>} units акумулятор
78
- * @returns {void}
79
- */
80
- function pushUnits(decl, exported, docStart, src, units) {
81
- if (!decl || typeof decl !== 'object') return
82
- const doc = precedingDoc(src, docStart)
83
- if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {
84
- const name = decl.id?.name
85
- if (!name) return
86
- units.push({
87
- name,
88
- kind: decl.type === 'ClassDeclaration' ? 'class' : 'function',
89
- exported,
90
- span: { start: decl.start, end: decl.end },
91
- body: src.slice(decl.start, decl.end),
92
- calls: collectCalls(decl),
93
- doc
94
- })
95
- return
96
- }
97
- if (decl.type === 'VariableDeclaration') {
98
- for (const d of decl.declarations ?? []) {
99
- const init = d.init
100
- const isFn = init && (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression')
101
- if (!isFn || d.id?.type !== 'Identifier') continue
102
- units.push({
103
- name: d.id.name,
104
- kind: 'const',
105
- exported,
106
- span: { start: init.start, end: init.end },
107
- body: src.slice(init.start, init.end),
108
- calls: collectCalls(init),
109
- doc
110
- })
111
- }
112
- }
113
- }
114
-
115
- /**
116
- * Юніт-шар для js/mjs/ts: top-level функції/класи/const-функції з тілом, JSDoc,
117
- * прапором експорту і ребрами call-graph (виклики ІНШИХ юнітів у тілі).
118
- * @param {string} src вміст файлу
119
- * @param {string} [relPath] шлях (для вибору мови oxc)
120
- * @returns {Array<{name:string, kind:string, exported:boolean, span:{start:number,end:number}, body:string, calls:string[], doc:string}>|null} юніти або null, якщо файл не парситься
121
- */
122
- export function extractUnitsJs(src, relPath = 'scan.ts') {
123
- const program = parseProgramOrNull(src, relPath)
124
- if (!program || !Array.isArray(program.body)) return null
125
-
126
- const units = []
127
- for (const node of program.body) {
128
- const isExport =
129
- (node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration') && node.declaration
130
- if (isExport) {
131
- pushUnits(node.declaration, true, node.start, src, units)
132
- } else {
133
- pushUnits(node, false, node.start, src, units)
134
- }
135
- }
136
-
137
- // Ребра call-graph: лишаємо тільки виклики інших внутрішніх юнітів
138
- const names = new Set(units.map(u => u.name))
139
- for (const u of units) u.calls = [...u.calls].filter(n => names.has(n) && n !== u.name)
140
- return units
141
- }
@@ -1,26 +0,0 @@
1
- ## `for...in` заборонено — рефакторити на `for...of`
2
-
3
- Конструкція `for (const k in obj)` обходить успадковані ключі прототипу, тому майже завжди тягне `Object.hasOwn(obj, k)`-guard. Заборонена у `@nitra/eslint-config` через `no-restricted-syntax` для `ForInStatement` (з версії **3.8.0**). У каноні oxlint (`guard-for-in: "deny"` у [oxlint-canonical.json](../tooling/data/tooling/oxlint-canonical.json)) лишається `guard-for-in` як часткова страховка (oxlint не підтримує `no-restricted-syntax`) — `checkOxlintRc` у `check/main.mjs` звіряє `.oxlintrc.json` проєкту з цим каноном.
4
-
5
- Замість цього обходь масив напряму, а об'єкт — через `Object.entries` / `Object.keys` / `Object.values`. У такому коді guard за `Object.hasOwn` стає непотрібним і має зникнути разом із `for...in`.
6
-
7
- ```javascript title="❌ до"
8
- for (const k in obj) {
9
- if (!Object.hasOwn(obj, k)) continue
10
- use(k, obj[k])
11
- }
12
-
13
- for (const i in arr) {
14
- use(arr[i])
15
- }
16
- ```
17
-
18
- ```javascript title="✅ після"
19
- for (const [k, v] of Object.entries(obj)) {
20
- use(k, v)
21
- }
22
-
23
- for (const item of arr) {
24
- use(item)
25
- }
26
- ```
@@ -1,19 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": [
6
- "eslint.config.js",
7
- "eslint.config.mjs",
8
- "**/package.json",
9
- ".oxlintrc.json",
10
- ".github/workflows/lint-js.yml",
11
- ".github/workflows/lint.yml",
12
- "knip.json",
13
- ".eslintrc",
14
- ".eslintrc.js",
15
- ".eslintrc.json",
16
- ".eslintrc.yml"
17
- ]
18
- }
19
- }
@@ -1,56 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: eslint-config.mjs
4
- resource: npm/rules/js/check/eslint-config.mjs
5
- docgen:
6
- crc: 6626a862
7
- model: manual
8
- ---
9
-
10
- ## Огляд
11
-
12
- Детекція воркспейс-типів (node/vue) репозиторію і чистий (read-only) планувальник
13
- scaffold/merge для `eslint.config.js` consumer-репо. Спільне джерело правди для
14
- detector-а `main.mjs` (перевірка, що кожен vue-воркспейс присутній у `vue: [...]`
15
- аргументах `getConfig`) і T0-фіксера `fix-check.mjs` (детерміноване створення або
16
- хірургічне оновлення конфігу — без повного перезапису файлу).
17
-
18
- ## Поведінка
19
-
20
- - Тип воркспейсу визначається за root `package.json`: записи `workspaces`
21
- (glob-и типу `packages/*` розгортаються у наявні директорії); воркспейс — vue,
22
- якщо його `package.json` має `vue`/`nuxt` у deps або в ньому є хоч один `.vue`
23
- файл (`node_modules`/`dist` ігноруються). Без `workspaces` класифікується сам
24
- корінь як `.`.
25
- - Merge наявного конфігу — хірургічний: додає відсутній `**/auto-imports.d.ts`
26
- у перший `ignores: [...]`, вставляє відсутні vue-воркспейси у `vue: [...]`
27
- (або нову властивість одразу після `getConfig({`), вилучає ці ж воркспейси з
28
- `node: [...]`. Кастомні ignores, overrides і коментарі не змінюються.
29
- - Fail-safe: якщо структура конфігу не розпізнається (немає `getConfig({`),
30
- файл не чіпається — порушення лишається для ручного розгляду.
31
-
32
- ## Публічний API
33
-
34
- - `detectWorkspaceTypes(cwd)` → `{ node: string[], vue: string[] }` — директорії
35
- за типами.
36
- - `parseVueList(raw)` → нормалізовані записи `vue: [...]` з тексту конфігу.
37
- - `renderEslintConfigScaffold(types)` → повний шаблон `eslint.config.js`
38
- (лише непорожні типи).
39
- - `mergeEslintConfig(raw, types)` → новий вміст (`=== raw`, якщо merge
40
- неможливий чи не потрібен).
41
- - `planEslintConfigFix(cwd)` → `{ path, content, message } | null` — ідемпотентний
42
- план для T0 (`null` на виправленому дереві).
43
- - Константи reason-ів: `ESLINT_CONFIG_MISSING`, `ESLINT_CONFIG_IGNORES`,
44
- `ESLINT_CONFIG_VUE_WORKSPACE`; `AUTO_IMPORTS_IGNORE`.
45
-
46
- ## Де використовується
47
-
48
- - `npm/rules/js/check/main.mjs` — detector (reason-и порушень, перевірка
49
- vue-воркспейсів).
50
- - `npm/rules/js/check/fix-check.mjs` — T0-фіксер (виконання плану).
51
-
52
- ## Гарантії поведінки
53
-
54
- - Read-only: модуль лише читає ФС і повертає план; запис виконує викликач.
55
- - Ідемпотентність: повторний `planEslintConfigFix` на виправленому дереві → `null`.
56
- - Биті/відсутні JSON-файли не кидають виняток (повертається `null`-об'єкт).
@@ -1,48 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-check.mjs
4
- resource: npm/rules/js/check/fix-check.mjs
5
- docgen:
6
- crc: 48182147
7
- model: manual
8
- ---
9
-
10
- ## Огляд
11
-
12
- T0-autofix для `js/check`: два детерміновані патерни, обидва без LLM.
13
-
14
- - `js-check-eslint-config` — scaffold/merge `eslint.config.js` за планом
15
- `planEslintConfigFix` (детекція воркспейс-типів node/vue). Раніше ці
16
- порушення йшли у LLM-ладдер, який переписував конфіг цілком і вгадував типи
17
- (інцидент: у vue-монорепо записано `getConfig({ node: ['npm'] })` — eslint
18
- перестав обробляти .vue файли).
19
- - `js-check-oxlintrc` — scaffold/merge `.oxlintrc.json` за планом
20
- `planOxlintrcFix` (`../tooling/main.mjs`). Раніше ці порушення теж йшли у
21
- LLM-ладдер: 15 КБ канону дешева модель не відтворює byte-perfect (verify
22
- fail), а дорожча не встигає за один rung-таймаут.
23
-
24
- ## Поведінка
25
-
26
- - `js-check-eslint-config` тригериться на reason-и `eslint-config-missing` /
27
- `eslint-config-ignores` / `eslint-config-vue-workspace`. `apply` перераховує
28
- план із поточного стану диска (ідемпотентно): відсутній конфіг —
29
- створюється з детектованими типами; наявний — зазнає хірургічного merge, без
30
- повного перезапису. Якщо план порожній (`null`) — жодних змін
31
- (`touchedFiles: []`).
32
- - `js-check-oxlintrc` тригериться на reason-и `oxlintrc-missing` /
33
- `oxlintrc-drift` (`OXLINTRC_MISSING` / `OXLINTRC_DRIFT` з `../tooling/main.mjs`).
34
- `apply` читає наявний `.oxlintrc.json` (`null`, якщо відсутній або невалідний
35
- JSON) і канон, будує злитий обʼєкт через `planOxlintrcFix` і перезаписує
36
- файл цілком (JSON, 2-space, з кінцевим переносом рядка).
37
- - Решта порушень `js/check` (engines, workflows) — поза цим T0, стандартний
38
- шлях (ladder/manual).
39
- - Обидва патерни викликають `ctx.recordWrite` перед записом (pre-image для
40
- central rollback).
41
-
42
- ## Гарантії поведінки
43
-
44
- - `js-check-eslint-config` записує лише `eslint.config.js`/`eslint.config.mjs`
45
- у корені репо; наявний конфіг ніколи не перезаписується цілком — тільки
46
- точкові вставки/заміни.
47
- - `js-check-oxlintrc` записує лише `.oxlintrc.json` у корені репо; результат
48
- завжди проходить `verifyOxlintRcAgainstCanonical` без ручного втручання.