@nitra/cursor 12.6.1 → 12.8.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 (372) hide show
  1. package/.claude-template/settings.template.json +1 -1
  2. package/.pi-template/extensions/n-cursor-adr/docs/index.md +2 -2
  3. package/CHANGELOG.md +25 -5
  4. package/bin/docs/n-cursor.md +4 -20
  5. package/bin/n-cursor.js +8 -54
  6. package/docs/index.md +3 -3
  7. package/docs/stryker.config.md +20 -28
  8. package/lib/docs/index.md +5 -5
  9. package/lib/docs/llm.md +4 -4
  10. package/package.json +2 -2
  11. package/rules/abie/docs/fix.md +8 -8
  12. package/rules/abie/docs/index.md +4 -3
  13. package/rules/abie/docs/main.md +29 -0
  14. package/rules/abie/js/docs/index.md +6 -6
  15. package/rules/abie/lib/docs/index.md +9 -9
  16. package/rules/abie/{fix.mjs → main.mjs} +5 -3
  17. package/rules/adr/docs/index.md +1 -0
  18. package/rules/adr/docs/main.md +29 -0
  19. package/rules/adr/{fix.mjs → main.mjs} +5 -3
  20. package/rules/bun/docs/fix.md +5 -5
  21. package/rules/bun/docs/index.md +4 -3
  22. package/rules/bun/docs/main.md +30 -0
  23. package/rules/bun/js/docs/index.md +2 -2
  24. package/rules/bun/js/docs/layout.md +11 -36
  25. package/rules/bun/{fix.mjs → main.mjs} +5 -3
  26. package/rules/capacitor/docs/fix.md +10 -10
  27. package/rules/capacitor/docs/index.md +4 -3
  28. package/rules/capacitor/docs/main.md +29 -0
  29. package/rules/capacitor/js/docs/index.md +2 -2
  30. package/rules/capacitor/{fix.mjs → main.mjs} +5 -3
  31. package/rules/changelog/docs/fix.md +11 -11
  32. package/rules/changelog/docs/index.md +4 -3
  33. package/rules/changelog/docs/main.md +27 -0
  34. package/rules/changelog/js/docs/consistency.md +12 -12
  35. package/rules/changelog/js/docs/index.md +2 -2
  36. package/rules/changelog/lib/docs/index.md +2 -2
  37. package/rules/changelog/main.mjs +20 -0
  38. package/rules/ci4/docs/fix.md +4 -4
  39. package/rules/ci4/docs/index.md +4 -3
  40. package/rules/ci4/docs/main.md +30 -0
  41. package/rules/ci4/js/docs/index.md +2 -2
  42. package/rules/ci4/main.mjs +20 -0
  43. package/rules/doc-files/docs/index.md +4 -3
  44. package/rules/doc-files/docs/main.md +31 -0
  45. package/rules/doc-files/js/docgen-crc.mjs +2 -8
  46. package/rules/doc-files/js/docgen-extract.mjs +5 -3
  47. package/rules/doc-files/js/docgen-files-batch.mjs +63 -4
  48. package/rules/doc-files/js/docgen-gen.mjs +11 -3
  49. package/rules/doc-files/js/docgen-judge-measure.mjs +67 -18
  50. package/rules/doc-files/js/docgen-judge.mjs +8 -1
  51. package/rules/doc-files/js/docgen-scan.mjs +99 -11
  52. package/rules/doc-files/js/docs/docgen-crc.md +25 -14
  53. package/rules/doc-files/js/docs/docgen-extract.md +15 -13
  54. package/rules/doc-files/js/docs/docgen-files-batch.md +15 -15
  55. package/rules/doc-files/js/docs/docgen-gen.md +15 -26
  56. package/rules/doc-files/js/docs/docgen-judge-measure.md +14 -12
  57. package/rules/doc-files/js/docs/docgen-scan.md +34 -34
  58. package/rules/doc-files/js/docs/index.md +16 -15
  59. package/rules/doc-files/js/docs/run-lint.md +27 -0
  60. package/rules/doc-files/{lint/lint.mjs → js/run-lint.mjs} +23 -9
  61. package/rules/doc-files/{js/lint.mjs → main.mjs} +60 -10
  62. package/rules/docker/docs/fix.md +6 -6
  63. package/rules/docker/docs/index.md +4 -3
  64. package/rules/docker/docs/main.md +28 -0
  65. package/rules/docker/js/docs/index.md +2 -2
  66. package/rules/docker/js/docs/lint.md +26 -54
  67. package/rules/docker/js/lint.mjs +11 -0
  68. package/rules/docker/lib/docker-hadolint.mjs +1 -1
  69. package/rules/docker/lib/docs/docker-hadolint.md +16 -173
  70. package/rules/docker/lib/docs/index.md +5 -5
  71. package/rules/docker/main.mjs +20 -0
  72. package/rules/efes/docs/fix.md +8 -8
  73. package/rules/efes/docs/index.md +4 -3
  74. package/rules/efes/docs/main.md +29 -0
  75. package/rules/efes/main.mjs +20 -0
  76. package/rules/feedback/docs/fix.md +5 -5
  77. package/rules/feedback/docs/index.md +4 -3
  78. package/rules/feedback/docs/main.md +30 -0
  79. package/rules/feedback/main.mjs +20 -0
  80. package/rules/ga/docs/fix.md +5 -5
  81. package/rules/ga/docs/index.md +4 -3
  82. package/rules/ga/docs/main.md +29 -0
  83. package/rules/ga/js/docs/index.md +3 -3
  84. package/rules/ga/{lint/lint.mjs → main.mjs} +36 -10
  85. package/rules/graphql/docs/fix.md +8 -8
  86. package/rules/graphql/docs/index.md +4 -3
  87. package/rules/graphql/docs/main.md +36 -0
  88. package/rules/graphql/js/docs/index.md +2 -2
  89. package/rules/graphql/lib/docs/index.md +2 -2
  90. package/rules/graphql/main.mjs +20 -0
  91. package/rules/hasura/docs/fix.md +11 -11
  92. package/rules/hasura/docs/index.md +4 -3
  93. package/rules/hasura/docs/main.md +30 -0
  94. package/rules/hasura/js/docs/index.md +2 -2
  95. package/rules/hasura/main.mjs +20 -0
  96. package/rules/image-avif/docs/fix.md +3 -3
  97. package/rules/image-avif/docs/index.md +4 -3
  98. package/rules/image-avif/docs/main.md +30 -0
  99. package/rules/image-avif/js/docs/avif_generation.md +20 -233
  100. package/rules/image-avif/js/docs/index.md +2 -2
  101. package/rules/image-avif/main.mjs +20 -0
  102. package/rules/image-compress/docs/fix.md +2 -2
  103. package/rules/image-compress/docs/index.md +4 -3
  104. package/rules/image-compress/docs/main.md +29 -0
  105. package/rules/image-compress/js/docs/index.md +3 -3
  106. package/rules/image-compress/js/docs/package_setup.md +12 -11
  107. package/rules/image-compress/{js/lint.mjs → main.mjs} +21 -5
  108. package/rules/js-bun-db/docs/fix.md +5 -5
  109. package/rules/js-bun-db/docs/index.md +4 -3
  110. package/rules/js-bun-db/docs/main.md +30 -0
  111. package/rules/js-bun-db/js/docs/index.md +2 -2
  112. package/rules/js-bun-db/lib/docs/index.md +2 -2
  113. package/rules/js-bun-db/main.mjs +20 -0
  114. package/rules/js-bun-redis/docs/fix.md +6 -6
  115. package/rules/js-bun-redis/docs/index.md +4 -3
  116. package/rules/js-bun-redis/docs/main.md +29 -0
  117. package/rules/js-bun-redis/js/docs/index.md +2 -2
  118. package/rules/js-bun-redis/lib/docs/index.md +2 -2
  119. package/rules/js-bun-redis/main.mjs +20 -0
  120. package/rules/js-lint/docs/fix.md +9 -9
  121. package/rules/js-lint/docs/index.md +4 -3
  122. package/rules/js-lint/docs/main.md +29 -0
  123. package/rules/js-lint/js/check.mjs +268 -0
  124. package/rules/js-lint/js/docs/check.md +39 -0
  125. package/rules/js-lint/js/docs/index.md +4 -4
  126. package/rules/js-lint/js/docs/tooling.md +12 -32
  127. package/rules/js-lint/js/tooling.mjs +1 -265
  128. package/rules/js-lint/{js/lint.mjs → main.mjs} +19 -2
  129. package/rules/js-lint-ci/docs/fix.md +3 -3
  130. package/rules/js-lint-ci/docs/index.md +4 -3
  131. package/rules/js-lint-ci/docs/main.md +27 -0
  132. package/rules/js-lint-ci/js/docs/index.md +2 -2
  133. package/rules/js-lint-ci/main.mjs +33 -0
  134. package/rules/js-mssql/docs/fix.md +5 -5
  135. package/rules/js-mssql/docs/index.md +4 -3
  136. package/rules/js-mssql/docs/main.md +30 -0
  137. package/rules/js-mssql/js/docs/index.md +2 -2
  138. package/rules/js-mssql/lib/docs/index.md +2 -2
  139. package/rules/js-mssql/main.mjs +20 -0
  140. package/rules/js-run/docs/fix.md +8 -8
  141. package/rules/js-run/docs/index.md +4 -3
  142. package/rules/js-run/docs/main.md +30 -0
  143. package/rules/js-run/js/docs/index.md +2 -2
  144. package/rules/js-run/lib/docs/index.md +7 -7
  145. package/rules/js-run/main.mjs +20 -0
  146. package/rules/k8s/docs/fix.md +4 -4
  147. package/rules/k8s/docs/index.md +4 -3
  148. package/rules/k8s/docs/main.md +40 -0
  149. package/rules/k8s/js/docs/index.md +12 -0
  150. package/rules/k8s/{lint/lint.mjs → main.mjs} +32 -10
  151. package/rules/nginx-default-tpl/docs/fix.md +7 -7
  152. package/rules/nginx-default-tpl/docs/index.md +4 -3
  153. package/rules/nginx-default-tpl/docs/main.md +30 -0
  154. package/rules/nginx-default-tpl/js/docs/index.md +2 -2
  155. package/rules/nginx-default-tpl/js/docs/template.md +2 -2
  156. package/rules/nginx-default-tpl/main.mjs +20 -0
  157. package/rules/npm-module/docs/fix.md +8 -8
  158. package/rules/npm-module/docs/index.md +4 -3
  159. package/rules/npm-module/docs/main.md +29 -0
  160. package/rules/npm-module/js/docs/index.md +5 -5
  161. package/rules/npm-module/js/docs/rule_meta.md +17 -16
  162. package/rules/npm-module/js/header_doc_pointer.mjs +1 -3
  163. package/rules/npm-module/js/rule_meta.mjs +13 -3
  164. package/rules/npm-module/main.mjs +20 -0
  165. package/rules/php/docs/fix.md +6 -6
  166. package/rules/php/docs/index.md +4 -3
  167. package/rules/php/docs/main.md +33 -0
  168. package/rules/php/js/docs/index.md +3 -3
  169. package/rules/php/js/docs/tooling.md +10 -10
  170. package/rules/php/{lint/lint.mjs → main.mjs} +32 -6
  171. package/rules/python/docs/fix.md +11 -11
  172. package/rules/python/docs/index.md +4 -3
  173. package/rules/python/docs/main.md +31 -0
  174. package/rules/python/js/docs/index.md +3 -3
  175. package/rules/python/js/docs/tooling.md +17 -17
  176. package/rules/python/{lint/lint.mjs → main.mjs} +31 -6
  177. package/rules/rego/docs/fix.md +5 -5
  178. package/rules/rego/docs/index.md +4 -3
  179. package/rules/rego/docs/main.md +37 -0
  180. package/rules/rego/js/docs/index.md +3 -3
  181. package/rules/rego/{lint/lint.mjs → main.mjs} +27 -5
  182. package/rules/release/docs/index.md +5 -4
  183. package/rules/release/docs/main.md +29 -0
  184. package/rules/release/docs/release.md +0 -3
  185. package/rules/release/lib/docs/index.md +4 -4
  186. package/rules/release/release.mdc +10 -0
  187. package/rules/rust/docs/fix.md +4 -4
  188. package/rules/rust/docs/index.md +4 -3
  189. package/rules/rust/docs/main.md +27 -0
  190. package/rules/rust/js/docs/index.md +3 -3
  191. package/rules/rust/lib/docs/index.md +2 -2
  192. package/rules/rust/{js/lint.mjs → main.mjs} +27 -4
  193. package/rules/security/docs/fix.md +6 -6
  194. package/rules/security/docs/index.md +4 -3
  195. package/rules/security/docs/main.md +28 -0
  196. package/rules/security/js/docs/index.md +4 -4
  197. package/rules/security/main.mjs +45 -0
  198. package/rules/style-lint/docs/fix.md +3 -3
  199. package/rules/style-lint/docs/index.md +4 -3
  200. package/rules/style-lint/docs/main.md +29 -0
  201. package/rules/style-lint/js/docs/index.md +3 -3
  202. package/rules/style-lint/{js/lint.mjs → main.mjs} +19 -1
  203. package/rules/tauri/docs/fix.md +11 -11
  204. package/rules/tauri/docs/index.md +4 -3
  205. package/rules/tauri/docs/main.md +29 -0
  206. package/rules/tauri/js/docs/index.md +3 -3
  207. package/rules/tauri/main.mjs +20 -0
  208. package/rules/test/docs/fix.md +5 -5
  209. package/rules/test/docs/index.md +4 -3
  210. package/rules/test/docs/main.md +30 -0
  211. package/rules/test/js/data/stryker_config/docs/index.md +4 -4
  212. package/rules/test/js/data/vitest_config/docs/index.md +2 -2
  213. package/rules/test/js/docs/index.md +7 -7
  214. package/rules/test/main.mjs +20 -0
  215. package/rules/text/docs/fix.md +11 -11
  216. package/rules/text/docs/index.md +4 -3
  217. package/rules/text/docs/main.md +29 -0
  218. package/rules/text/{lint → js}/cspell-fix.mjs +7 -2
  219. package/rules/text/js/docs/cspell-fix.md +30 -0
  220. package/rules/text/js/docs/formatting.md +12 -45
  221. package/rules/text/js/docs/index.md +8 -4
  222. package/rules/text/js/docs/run-dotenv-linter.md +31 -0
  223. package/rules/text/js/docs/run-shellcheck.md +28 -0
  224. package/rules/text/js/docs/run-v8r.md +29 -0
  225. package/rules/text/{lint/lint.mjs → main.mjs} +41 -10
  226. package/rules/tool-surface/docs/index.md +4 -3
  227. package/rules/tool-surface/docs/main.md +29 -0
  228. package/rules/tool-surface/main.mjs +20 -0
  229. package/rules/tool-surface/meta.json +6 -1
  230. package/rules/vue/docs/fix.md +6 -6
  231. package/rules/vue/docs/index.md +4 -3
  232. package/rules/vue/docs/main.md +29 -0
  233. package/rules/vue/js/docs/index.md +2 -2
  234. package/rules/vue/lib/docs/index.md +2 -2
  235. package/rules/vue/main.mjs +20 -0
  236. package/rules/worktree/docs/fix.md +11 -11
  237. package/rules/worktree/docs/index.md +4 -3
  238. package/rules/worktree/docs/main.md +28 -0
  239. package/rules/worktree/main.mjs +20 -0
  240. package/scripts/coverage-classify/docs/index.md +6 -6
  241. package/scripts/dispatcher/docs/index.md +2 -2
  242. package/scripts/docs/index.md +16 -15
  243. package/scripts/docs/post-tool-use-check.md +29 -0
  244. package/scripts/docs/sync-claude-config.md +64 -92
  245. package/scripts/lib/adr/docs/normalize-cli.md +0 -3
  246. package/scripts/lib/adr/docs/normalize-pipeline.md +0 -3
  247. package/scripts/lib/docs/gha-workflow.md +25 -317
  248. package/scripts/lib/docs/index.md +36 -35
  249. package/scripts/lib/docs/list-project-rules-mdc.md +5 -4
  250. package/scripts/lib/docs/list-rule-ids.md +15 -148
  251. package/scripts/lib/docs/read-n-cursor-config-lite.md +12 -16
  252. package/scripts/lib/docs/run-lint-step.md +13 -13
  253. package/scripts/lib/docs/run-lint.md +30 -0
  254. package/scripts/lib/docs/run-rule-cli.md +14 -10
  255. package/scripts/lib/docs/run-standard-lint.md +29 -10
  256. package/scripts/lib/docs/run-standard-rule.md +12 -11
  257. package/scripts/lib/docs/timing-summary.md +11 -12
  258. package/scripts/lib/docs/worktree-notice.md +0 -3
  259. package/scripts/lib/fix/analyze-escalation.mjs +4 -1
  260. package/scripts/lib/fix/docs/index.md +11 -10
  261. package/scripts/lib/fix/docs/orchestrator.md +23 -18
  262. package/scripts/lib/fix/docs/run-conformance-check.md +33 -0
  263. package/scripts/lib/fix/docs/run-fix-check.md +3 -3
  264. package/scripts/lib/fix/docs/t0.md +10 -9
  265. package/scripts/lib/fix/orchestrator.mjs +31 -8
  266. package/scripts/lib/fix/{run-fix-check.mjs → run-conformance-check.mjs} +13 -13
  267. package/scripts/lib/fix/t0.mjs +6 -3
  268. package/scripts/lib/list-project-rules-mdc.mjs +1 -1
  269. package/scripts/lib/list-rule-ids.mjs +12 -3
  270. package/scripts/lib/read-n-cursor-config-lite.mjs +2 -2
  271. package/{rules/lint/js/orchestrate.mjs → scripts/lib/run-lint.mjs} +42 -22
  272. package/scripts/lib/run-rule-cli.mjs +4 -4
  273. package/scripts/lib/run-standard-lint.mjs +19 -6
  274. package/scripts/lib/run-standard-rule.mjs +4 -4
  275. package/scripts/lib/timing-summary.mjs +1 -1
  276. package/scripts/{post-tool-use-fix.mjs → post-tool-use-check.mjs} +9 -9
  277. package/scripts/sync-claude-config.mjs +2 -2
  278. package/scripts/utils/docs/index.md +14 -14
  279. package/skills/doc-aggregate/js/docs/index.md +3 -3
  280. package/skills/doc-files/.changes/260612-0002.md +1 -0
  281. package/skills/doc-files/.changes/260612-0006.md +1 -0
  282. package/skills/doc-files/.changes/260612-0008.md +1 -0
  283. package/skills/doc-files/.changes/260612-0012.md +1 -0
  284. package/skills/doc-files/.changes/260612-0031.md +1 -0
  285. package/skills/doc-files/.changes/260612-0036.md +1 -0
  286. package/skills/doc-files/.changes/260612-0114.md +1 -0
  287. package/skills/start-check/js/docs/index.md +2 -2
  288. package/skills/taze/js/docs/index.md +2 -2
  289. package/types/bin/n-cursor.d.ts +1 -1
  290. package/rules/changelog/fix.mjs +0 -18
  291. package/rules/ci4/fix.mjs +0 -18
  292. package/rules/doc-files/fix.mjs +0 -19
  293. package/rules/doc-files/js/docs/lint.md +0 -34
  294. package/rules/doc-files/lint/docs/index.md +0 -11
  295. package/rules/doc-files/lint/docs/lint.md +0 -35
  296. package/rules/docker/fix.mjs +0 -18
  297. package/rules/docker/lint/docs/index.md +0 -11
  298. package/rules/docker/lint/docs/lint.md +0 -200
  299. package/rules/docker/lint/lint.mjs +0 -95
  300. package/rules/efes/fix.mjs +0 -18
  301. package/rules/feedback/fix.mjs +0 -18
  302. package/rules/ga/fix.mjs +0 -18
  303. package/rules/ga/js/docs/lint.md +0 -20
  304. package/rules/ga/js/lint.mjs +0 -12
  305. package/rules/ga/lint/docs/index.md +0 -11
  306. package/rules/ga/lint/docs/lint.md +0 -31
  307. package/rules/graphql/fix.mjs +0 -18
  308. package/rules/hasura/fix.mjs +0 -18
  309. package/rules/image-avif/fix.mjs +0 -18
  310. package/rules/image-compress/fix.mjs +0 -18
  311. package/rules/image-compress/js/docs/lint.md +0 -24
  312. package/rules/js-bun-db/fix.mjs +0 -18
  313. package/rules/js-bun-redis/fix.mjs +0 -18
  314. package/rules/js-lint/fix.mjs +0 -18
  315. package/rules/js-lint/js/docs/lint.md +0 -32
  316. package/rules/js-lint-ci/fix.mjs +0 -18
  317. package/rules/js-lint-ci/js/docs/lint.md +0 -22
  318. package/rules/js-lint-ci/js/lint.mjs +0 -15
  319. package/rules/js-mssql/fix.mjs +0 -18
  320. package/rules/js-run/fix.mjs +0 -18
  321. package/rules/k8s/fix.mjs +0 -18
  322. package/rules/k8s/js/lint.mjs +0 -14
  323. package/rules/k8s/lint/docs/index.md +0 -11
  324. package/rules/k8s/lint/docs/lint.md +0 -413
  325. package/rules/lint/docs/fix.md +0 -25
  326. package/rules/lint/docs/index.md +0 -11
  327. package/rules/lint/fix.mjs +0 -18
  328. package/rules/lint/js/docs/index.md +0 -11
  329. package/rules/lint/js/docs/orchestrate.md +0 -31
  330. package/rules/lint/meta.json +0 -1
  331. package/rules/nginx-default-tpl/fix.mjs +0 -18
  332. package/rules/npm-module/fix.mjs +0 -18
  333. package/rules/php/fix.mjs +0 -18
  334. package/rules/php/js/docs/lint.md +0 -20
  335. package/rules/php/js/lint.mjs +0 -15
  336. package/rules/php/lint/docs/index.md +0 -11
  337. package/rules/php/lint/docs/lint.md +0 -219
  338. package/rules/python/fix.mjs +0 -18
  339. package/rules/python/js/docs/lint.md +0 -21
  340. package/rules/python/js/lint.mjs +0 -14
  341. package/rules/python/lint/docs/index.md +0 -11
  342. package/rules/python/lint/docs/lint.md +0 -29
  343. package/rules/rego/fix.mjs +0 -18
  344. package/rules/rego/js/docs/lint.md +0 -21
  345. package/rules/rego/js/lint.mjs +0 -12
  346. package/rules/rego/lint/docs/index.md +0 -11
  347. package/rules/rego/lint/docs/lint.md +0 -208
  348. package/rules/rust/fix.mjs +0 -18
  349. package/rules/rust/js/docs/lint.md +0 -21
  350. package/rules/security/fix.mjs +0 -18
  351. package/rules/security/js/docs/lint.md +0 -175
  352. package/rules/security/js/lint.mjs +0 -26
  353. package/rules/style-lint/fix.mjs +0 -18
  354. package/rules/style-lint/js/docs/lint.md +0 -31
  355. package/rules/tauri/fix.mjs +0 -18
  356. package/rules/test/fix.mjs +0 -18
  357. package/rules/text/fix.mjs +0 -18
  358. package/rules/text/js/docs/lint.md +0 -23
  359. package/rules/text/js/lint.mjs +0 -15
  360. package/rules/text/lint/docs/cspell-fix.md +0 -32
  361. package/rules/text/lint/docs/index.md +0 -15
  362. package/rules/text/lint/docs/lint.md +0 -36
  363. package/rules/text/lint/docs/run-dotenv-linter.md +0 -161
  364. package/rules/text/lint/docs/run-shellcheck.md +0 -216
  365. package/rules/text/lint/docs/run-v8r.md +0 -201
  366. package/rules/tool-surface/fix.mjs +0 -18
  367. package/rules/vue/fix.mjs +0 -18
  368. package/rules/worktree/fix.mjs +0 -18
  369. /package/rules/release/{fix.mjs → main.mjs} +0 -0
  370. /package/rules/text/{lint → js}/run-dotenv-linter.mjs +0 -0
  371. /package/rules/text/{lint → js}/run-shellcheck.mjs +0 -0
  372. /package/rules/text/{lint → js}/run-v8r.mjs +0 -0
@@ -0,0 +1,36 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/graphql/main.mjs
5
+ docgen:
6
+ crc: 762b6875
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Модуль валідує дані на відповідність політикам, використовуючи конфігурації з meta.json, логіку визначення зацікавленості та контекст. При виконанні як CLI, він завантажує конфігурації, перевіряє білий список, агрегує стан валідації та завершує роботу відповідним кодом.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Викликається функція `run` для виконання перевірки.
18
+ 2. Виконання перевірки застосовує:
19
+ - Конфігурації, визначені у `meta.json`.
20
+ - Логіку, пов'язану з JS-зацікавленістю.
21
+ - Політику, визначену в контексті.
22
+ - Посилання на MDC.
23
+ 3. Якщо скрипт виконується як окремий інструмент (CLI), виконується повний цикл правил:
24
+ - Завантаження конфігурацій.
25
+ - Перевірка білого списку.
26
+ - Зведення результатів.
27
+ - Вихід із кодом, що інформує про успіх чи порушення.
28
+
29
+ ## Публічний API
30
+
31
+ run — єдиний вхідний пункт правила, який виконує послідовність перевірок: застосовує логіку, обробляє JS-специфічні моменти, перевіряє політику та посилання на MDC.
32
+
33
+ ## Гарантії поведінки
34
+
35
+ - Read-only: не виконує операцій запису (ФС/БД).
36
+ - Кешує результати в межах одного прогону.
@@ -6,6 +6,6 @@ resource: npm/rules/graphql/js/
6
6
 
7
7
  # npm/rules/graphql/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | ------------------------- | --------- |
11
11
  | [tooling.mjs](tooling.md) | JS Module |
@@ -6,6 +6,6 @@ resource: npm/rules/graphql/lib/
6
6
 
7
7
  # npm/rules/graphql/lib
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | ------------------------------------------- | --------- |
11
11
  | [graphql-gql-scan.mjs](graphql-gql-scan.md) | JS Module |
@@ -0,0 +1,20 @@
1
+ import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
2
+ import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
3
+
4
+ /**
5
+ * Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня: applies →
6
+ * JS-concerns → policy → mdc-refs (через runStandardRule). Lint-поверхні правило не має
7
+ * (`meta.json` без `lint`), тож експорту `lint` тут немає.
8
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
9
+ * @param {import('../../scripts/lib/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
10
+ * @returns {Promise<number>} 0 — OK, 1 — порушення
11
+ */
12
+ export function run(ctx) {
13
+ return runStandardRule(import.meta.dirname, ctx)
14
+ }
15
+
16
+ if (isRunAsCli(import.meta.url)) {
17
+ // Standalone: bun rules/<id>/main.mjs — повний еквівалент `npx @nitra/cursor check <id>`
18
+ // (config-loading + whitelist + summary): library-роль (run) + standalone-роль (CLI-блок).
19
+ process.exitCode = await runRuleCli(import.meta.dirname)
20
+ }
@@ -14,18 +14,18 @@ docgen:
14
14
  ## Поведінка
15
15
 
16
16
  1. Запуск правила.
17
- * Приймає контекст прогону.
18
- * Виконує застосування JS-занепокоєних.
19
- * Застосовує політику.
20
- * Генерує посилання на MDC.
21
- * Повертає результат прогону.
17
+ - Приймає контекст прогону.
18
+ - Виконує застосування JS-занепокоєних.
19
+ - Застосовує політику.
20
+ - Генерує посилання на MDC.
21
+ - Повертає результат прогону.
22
22
  2. Запуск правила у режимі CLI.
23
- * Виконується при запуску через CLI.
24
- * Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
25
- * Виконує завантаження конфігурації.
26
- * Виконує перевірку дозволів.
27
- * Генерує підсумок.
28
- * Визначає код виходу.
23
+ - Виконується при запуску через CLI.
24
+ - Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
25
+ - Виконує завантаження конфігурації.
26
+ - Виконує перевірку дозволів.
27
+ - Генерує підсумок.
28
+ - Визначає код виходу.
29
29
 
30
30
  ## Публічний API
31
31
 
@@ -6,6 +6,7 @@ resource: npm/rules/hasura/
6
6
 
7
7
  # npm/rules/hasura
8
8
 
9
- | Файл | Тип |
10
- |---|---|
11
- | [fix.mjs](fix.md) | JS Module |
9
+ | Файл | Тип |
10
+ | ------------------- | --------- |
11
+ | [fix.mjs](fix.md) | JS Module |
12
+ | [main.mjs](main.md) | JS Module |
@@ -0,0 +1,30 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/hasura/main.mjs
5
+ docgen:
6
+ crc: 762b6875
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Модуль виконує логіку, визначену у конфігурації `meta.json`. Він валідує дані відповідно до правил, застосовує визначену політику та збирає посилання до MDC. При запуску через публічну функцію `run` ініціюється виконання правила. Модуль є read-only і не виконує операцій запису у файлову систему чи бази даних.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Викликається публічна функція `run`.
18
+ 2. Виконується перевірка на відповідність конфігурації, що описується у `meta.json`.
19
+ 3. Виконується застосування політики, що визначається в конфігурації.
20
+ 4. Здійснюється збір посилань до MDC.
21
+ 5. Якщо код виконується як окрема утиліта (CLI), викликається механізм виконання правила.
22
+
23
+ ## Публічний API
24
+
25
+ run — виконує повний цикл перевірки: застосовує логіку, аналізує JS-залежності, перевіряє політику та посилання на MDC.
26
+
27
+ ## Гарантії поведінки
28
+
29
+ - Read-only: не виконує операцій запису (ФС/БД).
30
+ - Кешує результати в межах одного прогону.
@@ -6,6 +6,6 @@ resource: npm/rules/hasura/js/
6
6
 
7
7
  # npm/rules/hasura/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | ------------------------------------- | --------- |
11
11
  | [internal_urls.mjs](internal_urls.md) | JS Module |
@@ -0,0 +1,20 @@
1
+ import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
2
+ import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
3
+
4
+ /**
5
+ * Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня: applies →
6
+ * JS-concerns → policy → mdc-refs (через runStandardRule). Lint-поверхні правило не має
7
+ * (`meta.json` без `lint`), тож експорту `lint` тут немає.
8
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
9
+ * @param {import('../../scripts/lib/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
10
+ * @returns {Promise<number>} 0 — OK, 1 — порушення
11
+ */
12
+ export function run(ctx) {
13
+ return runStandardRule(import.meta.dirname, ctx)
14
+ }
15
+
16
+ if (isRunAsCli(import.meta.url)) {
17
+ // Standalone: bun rules/<id>/main.mjs — повний еквівалент `npx @nitra/cursor check <id>`
18
+ // (config-loading + whitelist + summary): library-роль (run) + standalone-роль (CLI-блок).
19
+ process.exitCode = await runRuleCli(import.meta.dirname)
20
+ }
@@ -12,9 +12,9 @@ docgen:
12
12
  ## Поведінка
13
13
 
14
14
  1. Запуск правила.
15
- * Приймає контекст прогону.
16
- * Виконує застосування JS-занепокоєних до політики до MDC-референсів.
17
- * Повертає результат.
15
+ - Приймає контекст прогону.
16
+ - Виконує застосування JS-занепокоєних до політики до MDC-референсів.
17
+ - Повертає результат.
18
18
 
19
19
  ## Публічний API
20
20
 
@@ -6,6 +6,7 @@ resource: npm/rules/image-avif/
6
6
 
7
7
  # npm/rules/image-avif
8
8
 
9
- | Файл | Тип |
10
- |---|---|
11
- | [fix.mjs](fix.md) | JS Module |
9
+ | Файл | Тип |
10
+ | ------------------- | --------- |
11
+ | [fix.mjs](fix.md) | JS Module |
12
+ | [main.mjs](main.md) | JS Module |
@@ -0,0 +1,30 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/image-avif/main.mjs
5
+ docgen:
6
+ crc: 762b6875
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Модуль виконує перевірку на основі логіки правил, використовуючи конфігурації з meta.json, політики та посилання на MDC. При запуску як окрема утиліта, він завантажує конфігурації, застосовує білі списки для фільтрації та формує зведений звіт. Результат виконання визначає код виходу процесу. Кешування відбувається у межах прогону. Модуль є Read-only, тобто не здійснює записів у файлову систему чи бази даних.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Викликається функція `run` для виконання перевірки.
18
+ 2. Виконання `run` застосовує логіку правила, включаючи обробку конфігурацій, перевірку політик та посилання на MDC.
19
+ 3. Якщо код виконується як окрема утиліта (CLI), ініціюється повний запуск правила.
20
+ 4. Запуск правила як утиліта включає завантаження конфігурацій, застосування білих списків та формування зведеного звіту.
21
+ 5. Результат виконання визначає код виходу процесу.
22
+
23
+ ## Публічний API
24
+
25
+ run — виконує основну логіку правила: застосовує перевірки до коду, аналізує аспекти JavaScript та застосовує політику, використовуючи посилання на метадані.
26
+
27
+ ## Гарантії поведінки
28
+
29
+ - Read-only: не виконує операцій запису (ФС/БД).
30
+ - Кешує результати в межах одного прогону.
@@ -3,244 +3,31 @@ type: JS Module
3
3
  title: avif_generation.mjs
4
4
  resource: npm/rules/image-avif/js/avif_generation.mjs
5
5
  docgen:
6
- crc: 101bb0dd
6
+ crc: 3f00d274
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
7
9
  ---
8
10
 
9
- Модуль реалізує перевірку правила `image-avif.mdc`: генерацію AVIF-двійників растрових зображень і ув'язування цих двійників із посиланнями у `.vue`- та `.html`-файлах монорепо. Експортує функцію `check`, яку викликає CLI `n-cursor` для команди `check image-avif` / `fix image-avif`.
11
+ Модуль трансформує посилання на растрові зображення у шаблонах `.vue` та `.html` у workspace-пакетах, замінюючи їх на формат AVIF. Процес залежить від конфігурацій, визначених у package.json. Модуль оновлює всі посилання на зображення, якщо перевірка AVIF не вимкнена, створюючи AVIF-двійники. Також він видаляє посилання на AVIF-файли, які не існують.
10
12
 
11
- Загальний сценарій роботи `check`:
13
+ ## Поведінка
12
14
 
13
- 1. **Pre-scan** шукає у `.vue`/`.html` хоча б одне raster-посилання (через `import x from '...png'` або `<img src="...png" />`), яке потенційно треба переписати на AVIF-двійник. Пакети з opt-out `"@nitra/minify-image": { "disable-avif": true }` у `package.json` пропускаються. Якщо жодного raster-посилання не знайдено модуль одразу повертає успіх і не запускає ні `npx`, ні rewrite, ні cleanup-пасс.
14
- 2. **AVIF-генерація** викликає `npx @nitra/minify-image --src=. --write --avif`, який створює AVIF-двійники поряд з оригіналами.
15
- 3. **Rewrite-пасс** — для кожного workspace-пакета (без opt-out) переписує raster-посилання у `.vue`/`.html` на `<...>.avif`, якщо двійник реально існує на диску. Якщо двійника немає (наприклад, оригіналу теж нема) — фейлить конкретне посилання.
16
- 4. **Cleanup-пасс** видаляє AVIF-сироти (`<...>.avif`, на які не лишилось жодного посилання у `.vue`/`.html` репозиторію), реалізуючи умову «AVIF лишається лише там, де заміна вдалася».
15
+ 1. Перевіряється, чи містить репозиторій посилання на raster-зображення у файлах `.vue` або `.html` у workspace-пакетах, які не мають вимкненої перевірки AVIF. Якщо посилань немає, процес AVIF-генерації та очищення пропускається.
16
+ 2. Запускається генерація AVIF-двійників за допомогою зовнішнього інструменту.
17
+ 3. Скануються workspace-пакети:
18
+ а. Визначається, чи вимкнено примусове застосування AVIF у пакеті через конфігурацію `package.json`. Якщо так, пакет пропускається для подальшої перевірки шаблонів.
19
+ б. Для пакетів, де AVIF не вимкнено, скануються файли `.vue` та `.html`.
20
+ в. У знайдених посиланнях на raster-зображення, якщо відповідний AVIF-двійник існує, посилання замінюється на `.avif`.
21
+ г. Якщо AVIF-двійник не існує, фіксується помилка.
22
+ д. Після обробки файлу, він записується з новими змінами.
23
+ е. Збирається список абсолютних шляхів AVIF-двійників, на які залишилося живе посилання.
24
+ 4. Видаляються AVIF-сироти — файли `.avif`, які не були відмічені як вжиті у кроці 3.б.
25
+ 5. Повертається код виходу, що відображає успішність виконання всіх етапів.
17
26
 
18
- Модуль свідомо не дублює перевірки cache/dependency policy з правила `image-compress`. Правило `image-avif` самостійне й вмикається лише там, де AVIF підтримується (адмінки), а не у публічних сайтах.
27
+ ## Публічний API
19
28
 
20
- ## Експорти / API
29
+ check генерує AVIF-зображення, автоматично замінює посилання на растрові зображення у `.vue`/`.html` файлах та очищає від неіснуючих AVIF-файлів.
21
30
 
22
- | Експорт | Тип | Призначення |
23
- | ------------- | ---------------- | ----------------------------------------------------------------------------------- |
24
- | `check(cwd?)` | `async function` | Точка входу перевірки `image-avif`; повертає exit-код (`0` — OK, `1` — є проблеми). |
31
+ ## Гарантії поведінки
25
32
 
26
- Інші функції у модулі (`packageHasAvifDisabled`, `resolveImageCandidates`, `checkVueAvifImportsInPackage`, `checkVueAvifImports`, `hasAnyVueRasterReference`, `runAvifGeneration`, `cleanupOrphanAvifs`) — внутрішні, не експортуються.
27
-
28
- ## Константи
29
-
30
- | Константа | Значення / форма | Призначення |
31
- | -------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
32
- | `MINIFY_PACKAGE_NAME` | `'@nitra/minify-image'` | Імʼя CLI-пакета, який генерує AVIF (викликається через `npx`). |
33
- | `PKG_CONFIG_FIELD` | `'@nitra/minify-image'` | Поле у `package.json` для конфігу `@nitra/minify-image` (`disable-avif: true` тощо). |
34
- | `CLEANUP_EXTRA_IGNORE_DIR_NAMES` | `Set` з `'build'`, `'android'`, `'ios'`, `'.output'`, `'.nuxt'`, `'.cache'` | Імена каталогів, які cleanup-пасс ігнорує додатково до стандартних (`node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next`, які вже скіпає `walkDir`). Це артефакти збірки / нативних платформ — AVIF всередині є продуктом попереднього `bun run build` / Capacitor sync. |
35
- | `VUE_RASTER_IMPORT_RE` | `/import\s+\w[\w$]\*\s+from\s+['"]([^'"\n]+\.(?:png | jpe?g | gif))['"]/giu` | Регексп для `import name from '...ext'` у `.vue`/`.html`; група 1 — повний шлях до зображення. |
36
- | `VUE_RASTER_STATIC_SRC_RE` | `/(?<![:-_.])\bsrc\s*=\s*['"]([^'"\s]+\.(?:png | jpe?g | gif))['"]/giu` | Регексп для статичних `<img src="...png" />` у шаблоні `.vue`. Lookbehind `(?<![:\-_.])` виключає `:src="..."` (реактивний JS-вираз), `data-src="..."` і `obj.src=...`. |
37
- | `VUE_AVIF_REF_RE` | `/['"]([^'"\s]+\.(?:png | jpe?g | gif)\.avif)['"]/giu` | Регексп для готових AVIF-посилань у `.vue`/`.html`. Використовується тільки для збору множини «живих» AVIF — щоб після rewrite знати, які `<...>.avif` ще на щось посилаються. |
38
-
39
- ## Типи
40
-
41
- ### `RewriteStats`
42
-
43
- ```text
44
- {
45
- rewrittenRefs: number // скільки конкретних посилань переписано на .avif
46
- rewrittenFiles: number // у скількох .vue/.html файлах хоч одне посилання змінилося
47
- failedRefs: number // скільки конкретних посилань не вдалося переписати (.avif не існував)
48
- }
49
- ```
50
-
51
- Аґреговані лічильники по проходу `check image-avif`, мутуються `checkVueAvifImportsInPackage`, потрапляють у фінальний `pass`-меседж.
52
-
53
- ## Функції
54
-
55
- ### `packageHasAvifDisabled(pkg)`
56
-
57
- - **Сигнатура:** `(pkg: Record<string, unknown>) => boolean`
58
- - **Параметри:**
59
- - `pkg` — розібраний обʼєкт `package.json` пакета.
60
- - **Повертає:** `true`, якщо у `package.json` встановлено `"@nitra/minify-image": { "disable-avif": true }`, інакше `false`.
61
- - **Side effects:** немає.
62
-
63
- ### `resolveImageCandidates(importPath, sourceAbsPath, packageRootAbs)`
64
-
65
- - **Сигнатура:** `(importPath: string, sourceAbsPath: string, packageRootAbs: string | null) => string[]`
66
- - **Параметри:**
67
- - `importPath` — шлях з `import x from '...'` або `src="..."`.
68
- - `sourceAbsPath` — абсолютний шлях файла-джерела (`.vue`/`.html`).
69
- - `packageRootAbs` — абсолютний корінь workspace-пакета, у якому лежить джерело (для резолвера `/path` як `<root>/public<path>`); `null`, якщо невідомо.
70
- - **Повертає:** впорядкований список абсолютних шляхів-кандидатів, по яких caller перевіряє існування `<candidate>` або `<candidate>.avif`.
71
- - **Правила резолва:**
72
- - `./x.png`, `../x.png` — відносно файла-джерела.
73
- - `/x.png` (Vite/Quasar-конвенція) — спочатку `<packageRoot>/public/x.png`, потім `<packageRoot>/x.png`, нарешті `<cwd>/x.png` як legacy fallback.
74
- - голий шлях з принаймні одним `/` (наприклад `assets/img.png`) — relative-to-source, плюс `<packageRoot>/public/<path>` як другий кандидат.
75
- - bare-шлях без `/` (наприклад `foo`) — ймовірно alias-resolver Vite/Webpack; повертається порожній список → caller просто пропускає посилання, не звітує fail.
76
- - **Side effects:** немає; шляхи будуються через `path.join`, файли не зачіпаються.
77
-
78
- ### `checkVueAvifImportsInPackage(packageRoot, otherRootsAbs, ignorePaths, usedAvifAbs, stats, fail, cwd)`
79
-
80
- - **Сигнатура:** `async (packageRoot: string, otherRootsAbs: string[], ignorePaths: string[], usedAvifAbs: Set<string>, stats: RewriteStats, fail: (msg: string) => void, cwd: string) => Promise<void>`
81
- - **Параметри:**
82
- - `packageRoot` — відносний шлях до кореня workspace-пакета (`'.'` або `'demo'`, тощо).
83
- - `otherRootsAbs` — абсолютні шляхи інших workspace-коренів; їхні піддерева пропускаються, щоб не сканувати один файл двічі.
84
- - `ignorePaths` — абсолютні шляхи каталогів, повністю виключених з обходу (зі `.cursorignore` тощо).
85
- - `usedAvifAbs` — мутабельна множина абсолютних шляхів `.avif`, що мають хоч одне посилання у `.vue`/`.html`; функція доповнює її.
86
- - `stats` — глобальні лічильники `RewriteStats`, мутуються тут.
87
- - `fail` — callback для звіту про помилку.
88
- - `cwd` — корінь репозиторію.
89
- - **Повертає:** `Promise<void>`, який резолвиться по завершенню обробки пакета.
90
- - **Side effects:**
91
- - Читає всі `.vue`/`.html` файли пакета через `walkDir`.
92
- - Перезаписує файли, у яких хоч одне посилання вдалось переписати (write-then-fail: запис відбувається ОДРАЗУ після обробки одного файла; провал на наступному файлі не відкочує вже записані зміни попередніх).
93
- - Мутує `usedAvifAbs` і `stats`.
94
- - Викликає `fail(msg)` для кожного raster-посилання, для якого AVIF-двійника немає на диску.
95
- - **Логіка:**
96
- - Збирає `targetFiles` — лише `.vue`/`.html` у `absRoot`, що не належать іншим workspace-кореням.
97
- - Для кожного файла застосовує `processMatches` із двома регекспами: `VUE_RASTER_IMPORT_RE` і `VUE_RASTER_STATIC_SRC_RE`. У `replaceAll` для кожного матчу резолвить кандидатів через `resolveImageCandidates`; якщо `existsSync(c + '.avif')` знаходить двійник — переписує посилання на `<importPath>.avif`, інкрементує `rewrittenRefs`, додає до `usedAvifAbs`; якщо ні — інкрементує `failedRefs` і викликає `fail`. Bare-alias (порожній список кандидатів) — пропускається без fail.
98
- - Окремо проходить `VUE_AVIF_REF_RE` по оновленому контенту й додає до `usedAvifAbs` усі AVIF-кандидати, які існують на диску (це треба, щоб cleanup-пасс не видалив AVIF, на який є посилання поза rewrite-патернами).
99
- - Якщо контент змінився — записує файл і інкрементує `rewrittenFiles`.
100
-
101
- ### `checkVueAvifImports(ignorePaths, usedAvifAbs, stats, pass, fail, cwd)`
102
-
103
- - **Сигнатура:** `async (ignorePaths: string[], usedAvifAbs: Set<string>, stats: RewriteStats, pass: (msg: string) => void, fail: (msg: string) => void, cwd: string) => Promise<string[]>`
104
- - **Параметри:**
105
- - `ignorePaths` — абсолютні шляхи каталогів, повністю виключених з обходу.
106
- - `usedAvifAbs` — мутабельна множина абсолютних шляхів `.avif`, що мають живі посилання (заповнюється у викликаних функціях).
107
- - `stats` — глобальні лічильники `RewriteStats`, мутуються нижче.
108
- - `pass` — callback при успішній перевірці пакета.
109
- - `fail` — callback при помилці.
110
- - `cwd` — корінь репозиторію.
111
- - **Повертає:** `Promise<string[]>` — абсолютні шляхи коренів пакетів з активним opt-out (`disable-avif: true`).
112
- - **Side effects:**
113
- - Читає кожен `package.json` workspace-пакета.
114
- - Для пакетів з opt-out — викликає `pass` з повідомленням про вимикач і додає корінь до `optedOutAbs`.
115
- - Для решти — викликає `checkVueAvifImportsInPackage`, який може писати у файли.
116
- - **Призначення `optedOutAbs`:** AVIF всередині opt-out пакета НЕ можна вважати сиротою лише на підставі відсутності посилань у його `.vue`/`.html` (ми взагалі не сканували його шаблони) — інакше cleanup помилково затирав би AVIF, що використовуються через alias / runtime-обчислений шлях / зовнішні посилання.
117
-
118
- ### `hasAnyVueRasterReference(ignorePaths, cwd)`
119
-
120
- - **Сигнатура:** `async (ignorePaths: string[], cwd: string) => Promise<boolean>`
121
- - **Параметри:**
122
- - `ignorePaths` — абсолютні шляхи каталогів, виключених з обходу.
123
- - `cwd` — корінь репозиторію.
124
- - **Повертає:** `true`, якщо у `.vue`/`.html` пакетів без opt-out знайдено принаймні одне raster-посилання (`VUE_RASTER_IMPORT_RE` або `VUE_RASTER_STATIC_SRC_RE`); `false` — інакше.
125
- - **Side effects:** немає (тільки читання файлів).
126
- - **Призначення:** дешевий pre-scan, що дозволяє пропустити дорогий `npx @nitra/minify-image --avif` і rewrite/cleanup у проєктах, де AVIF не вживається.
127
- - **Нюанс:** перед кожним `test`/`replaceAll` функція скидає `lastIndex` регекспа на `0`, оскільки регекспи з прапором `g` тримають стан між викликами.
128
-
129
- ### `runAvifGeneration(cwd)`
130
-
131
- - **Сигнатура:** `(cwd: string) => void`
132
- - **Параметри:**
133
- - `cwd` — корінь репозиторію, у якому запускається `npx`.
134
- - **Повертає:** `void`.
135
- - **Side effects:**
136
- - Викликає `spawnSync(npxPath, ['@nitra/minify-image', '--src=.', '--write', '--avif'], { stdio: 'inherit', cwd, env })`, який генерує AVIF-двійники.
137
- - Логує попередження (`console.log`) при відсутності `npx` у PATH, помилці спавна або ненульовому коді виходу — без падіння перевірки.
138
- - **Best-effort семантика:** якщо мережа/кеш недоступні чи бінарника нема — лог-варн без винятку; перевірка vue/html все одно виявить файли, для яких не вистачає `.avif`.
139
- - **Опт-аут запуску:** якщо `process.env.NITRA_CURSOR_NO_AVIF_RUN === '1'` — функція no-op (потрібно для тестів та ізольованих середовищ).
140
- - **Resolver `npx`:** `resolveCmd('npx')` повертає повний шлях; якщо `null` — функція друкує попередження і виходить.
141
-
142
- ### `cleanupOrphanAvifs(usedAvifAbs, optedOutAbs, ignorePaths, cwd)`
143
-
144
- - **Сигнатура:** `async (usedAvifAbs: Set<string>, optedOutAbs: string[], ignorePaths: string[], cwd: string) => Promise<number>`
145
- - **Параметри:**
146
- - `usedAvifAbs` — абсолютні шляхи `.avif`, що мають живі посилання (їх не чіпаємо).
147
- - `optedOutAbs` — абсолютні шляхи коренів opt-out пакетів; AVIF під ними не вважаємо сиротами.
148
- - `ignorePaths` — абсолютні шляхи каталогів, виключених з обходу.
149
- - `cwd` — корінь репозиторію.
150
- - **Повертає:** `Promise<number>` — кількість видалених сиріт.
151
- - **Side effects:** видаляє `.avif` файли через `unlink`.
152
- - **Фільтр кандидатів:**
153
- - файл закінчується на `.avif`;
154
- - не присутній у `usedAvifAbs`;
155
- - не лежить під жодним з `optedOutAbs`;
156
- - жоден сегмент шляху не входить у `CLEANUP_EXTRA_IGNORE_DIR_NAMES` (`build`, `android`, `ios`, `.output`, `.nuxt`, `.cache`).
157
- - **Ідемпотентність:** opt-out гарантує, що повторний `check image-avif` не починає циклічно видаляти AVIF в пакетах, що вимкнули правило (наприклад, мобільний бандл).
158
-
159
- ### `check(cwd = process.cwd())` — експортована точка входу
160
-
161
- - **Сигнатура:** `async (cwd?: string) => Promise<number>`
162
- - **Параметри:**
163
- - `cwd` — корінь репозиторію; за замовчуванням `process.cwd()`.
164
- - **Повертає:** `Promise<number>` — exit-код (`0` — OK, `1` — є проблеми), отриманий з `reporter.getExitCode()`.
165
- - **Side effects:**
166
- - Створює `createCheckReporter()` для агрегації pass/fail-меседжів.
167
- - Завантажує `ignorePaths` через `loadCursorIgnorePaths(cwd)`.
168
- - Якщо `hasAnyVueRasterReference` повернула `false` — викликає `pass(...)` з відповідним повідомленням і одразу повертає exit-код (без AVIF-генерації, rewrite, cleanup).
169
- - Інакше: викликає `runAvifGeneration(cwd)`, потім `checkVueAvifImports(...)` (rewrite + збір usedAvifAbs + список optedOutAbs), потім `cleanupOrphanAvifs(...)`, фіксує підсумкове `pass(...)` з кількістю переписаних посилань, файлів, видалених сиріт і фейлів. Фейли всередині rewrite-пасу йдуть через `fail(...)` і впливають на exit-код.
170
-
171
- ## Залежності
172
-
173
- ### Node.js builtins
174
-
175
- - `node:fs` — `existsSync` (синхронна перевірка наявності файла, бо викликається у тісному `replaceAll`-циклі).
176
- - `node:fs/promises` — `readFile`, `writeFile`, `unlink`.
177
- - `node:path` — `join`, `relative`.
178
- - `node:child_process` — `spawnSync` для запуску `npx @nitra/minify-image`.
179
- - `node:process` — `env` (для опт-ауту `NITRA_CURSOR_NO_AVIF_RUN=1`); також глобально використовується `process.cwd()` у `resolveImageCandidates` і дефолтному параметрі `check`.
180
-
181
- ### Внутрішні модулі (n-cursor)
182
-
183
- - `../../../scripts/lib/check-reporter.mjs` → `createCheckReporter` — фабрика обʼєкта зі `pass`/`fail`/`getExitCode`.
184
- - `../../../scripts/lib/load-cursor-config.mjs` → `loadCursorIgnorePaths` — завантажує абсолютні шляхи каталогів, які треба ігнорувати при обході.
185
- - `../../../scripts/utils/resolve-cmd.mjs` → `resolveCmd` — резолвить абсолютний шлях до CLI-бінарника у `PATH`.
186
- - `../../../scripts/utils/walkDir.mjs` → `walkDir` — рекурсивний обхід директорії з вбудованим скіпом `node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next` та користувацьким callback.
187
- - `../../../scripts/lib/workspaces.mjs` → `getMonorepoPackageRootDirs` — повертає відносні шляхи коренів workspace-пакетів монорепо.
188
-
189
- ### Зовнішні CLI
190
-
191
- - `npx` — резолвиться через `resolveCmd`; запускає `@nitra/minify-image` через `npx`.
192
- - `@nitra/minify-image` — окремий npm-пакет, який і генерує AVIF-двійники (`--src=. --write --avif`).
193
-
194
- ## Потік виконання / Використання
195
-
196
- ### Виклик з CLI
197
-
198
- Модуль викликається з реєстру правил `n-cursor` як check-функція правила `image-avif`. Очікувана крапка входу:
199
-
200
- ```js
201
- import { check } from './npm/rules/image-avif/js/avif_generation.mjs'
202
-
203
- const exitCode = await check(process.cwd())
204
- process.exit(exitCode)
205
- ```
206
-
207
- ### Послідовність кроків у `check(cwd)`
208
-
209
- 1. Створюється reporter (`createCheckReporter`).
210
- 2. Завантажується `ignorePaths` через `loadCursorIgnorePaths(cwd)`.
211
- 3. **Pre-scan**: `hasAnyVueRasterReference(ignorePaths, cwd)` обходить пакети без opt-out, шукає raster-посилання. Якщо нема — `pass(...)` і ранній вихід.
212
- 4. **AVIF-генерація**: `runAvifGeneration(cwd)` — викликає `npx @nitra/minify-image --src=. --write --avif`, який створює AVIF-двійники. Опціонально вимикається через `NITRA_CURSOR_NO_AVIF_RUN=1`.
213
- 5. **Rewrite-пасс**: `checkVueAvifImports(...)` обходить кожен workspace-пакет:
214
- - Якщо `package.json` має `disable-avif: true` — `pass(...)` і додає корінь у `optedOutAbs`.
215
- - Інакше — `checkVueAvifImportsInPackage(...)` обробляє кожен `.vue`/`.html` у пакеті: переписує raster-посилання на `.avif` (якщо двійник існує), фейлить ті, для яких двійника нема, збирає `usedAvifAbs`.
216
- 6. **Cleanup-пасс**: `cleanupOrphanAvifs(usedAvifAbs, optedOutAbs, ignorePaths, cwd)` видаляє `.avif`, на які не лишилось живих посилань, з врахуванням opt-out і списку артефактів збірки.
217
- 7. Фінальний `pass(...)` з підсумком: скільки посилань переписано, у скількох файлах, скільки сиріт видалено, скільки фейлів rewrite.
218
- 8. Повертається `reporter.getExitCode()` — `1`, якщо був хоч один `fail`, інакше `0`.
219
-
220
- ### Опт-аут на рівні пакета
221
-
222
- Щоб вимкнути AVIF-перевірку у конкретному workspace-пакеті, у його `package.json` додається:
223
-
224
- ```json
225
- {
226
- "@nitra/minify-image": {
227
- "disable-avif": true
228
- }
229
- }
230
- ```
231
-
232
- Наслідки:
233
-
234
- - pre-scan ігнорує цей пакет (його raster-посилання не провокують запуск `npx --avif`);
235
- - rewrite-пасс не сканує і не змінює його `.vue`/`.html`;
236
- - cleanup-пасс не видаляє `.avif` під його коренем (бо ми не зібрали `usedAvifAbs` для нього).
237
-
238
- ### Опт-аут запуску `npx`
239
-
240
- Змінна середовища `NITRA_CURSOR_NO_AVIF_RUN=1` повністю вимикає виклик `npx @nitra/minify-image --avif`. Pre-scan, rewrite і cleanup при цьому працюють як зазвичай — потрібно для юніт-тестів і ізольованих CI-середовищ.
241
-
242
- ### Семантика помилок
243
-
244
- - **Бракує `.avif`-двійника** — fail на конкретний `.vue`/`.html`-файл і конкретний `importPath` з підказкою про `npx @nitra/cursor fix image-avif` та локальний opt-out.
245
- - **`npx` недоступний / падає** — лише warn у `console.log`, без переривання перевірки; fail прийде пізніше від rewrite-пасу, якщо `.avif` так і не з'явилися.
246
- - **Bare alias** (`'foo'` без `/`) — резолвера нема, посилання пропускається без fail.
33
+ - Кешує результати в межах одного прогону.
@@ -6,6 +6,6 @@ resource: npm/rules/image-avif/js/
6
6
 
7
7
  # npm/rules/image-avif/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | ----------------------------------------- | --------- |
11
11
  | [avif_generation.mjs](avif_generation.md) | JS Module |
@@ -0,0 +1,20 @@
1
+ import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
2
+ import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
3
+
4
+ /**
5
+ * Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня: applies →
6
+ * JS-concerns → policy → mdc-refs (через runStandardRule). Lint-поверхні правило не має
7
+ * (`meta.json` без `lint`), тож експорту `lint` тут немає.
8
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
9
+ * @param {import('../../scripts/lib/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
10
+ * @returns {Promise<number>} 0 — OK, 1 — порушення
11
+ */
12
+ export function run(ctx) {
13
+ return runStandardRule(import.meta.dirname, ctx)
14
+ }
15
+
16
+ if (isRunAsCli(import.meta.url)) {
17
+ // Standalone: bun rules/<id>/main.mjs — повний еквівалент `npx @nitra/cursor check <id>`
18
+ // (config-loading + whitelist + summary): library-роль (run) + standalone-роль (CLI-блок).
19
+ process.exitCode = await runRuleCli(import.meta.dirname)
20
+ }
@@ -12,8 +12,8 @@ docgen:
12
12
  ## Поведінка
13
13
 
14
14
  1. Запуск правила.
15
- * Приймає контекст прогону.
16
- * Повертає результат прогону.
15
+ - Приймає контекст прогону.
16
+ - Повертає результат прогону.
17
17
 
18
18
  ## Публічний API
19
19
 
@@ -6,6 +6,7 @@ resource: npm/rules/image-compress/
6
6
 
7
7
  # npm/rules/image-compress
8
8
 
9
- | Файл | Тип |
10
- |---|---|
11
- | [fix.mjs](fix.md) | JS Module |
9
+ | Файл | Тип |
10
+ | ------------------- | --------- |
11
+ | [fix.mjs](fix.md) | JS Module |
12
+ | [main.mjs](main.md) | JS Module |
@@ -0,0 +1,29 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/image-compress/main.mjs
5
+ docgen:
6
+ crc: abe40746
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 90
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Модуль забезпечує механізми для виконання та валідації контенту відповідно до визначених правил. Функція `run` виконує перевірку відповідності контенту визначеним критеріям у межах поточного контексту прогону. Функція `lint` виконує виявлення або стиснення зображень залежно від режиму `readOnly`.
14
+
15
+ ## Поведінка
16
+
17
+ run виконує стандартну перевірку, використовуючи контекст прогону.
18
+ lint виконує перевірку або стиснення зображень, залежно від опцій: якщо `readOnly` встановлено, виконується лише детект, інакше виконується стиснення.
19
+
20
+ ## Публічний API
21
+
22
+ run — головна точка входу для виконання правил, де відбувається перевірка на відповідність вимогам (JS-занепокоєння $\rightarrow$ політика $\rightarrow$ посилання MDC).
23
+ lint — перевірка зображень за допомогою `@nitra/minify-image`, що може працювати у режимі лише читання або з можливістю автоматичного виправлення.
24
+
25
+ ## Гарантії поведінки
26
+
27
+ - Read-only: не виконує операцій запису (ФС/БД).
28
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
29
+ - Кешує результати в межах одного прогону.