@7n/rules 1.0.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 (1219) hide show
  1. package/.claude-template/hooks/capture-decisions.sh +355 -0
  2. package/.claude-template/hooks/lib/tooling-only.sh +77 -0
  3. package/.claude-template/hooks/normalize-decisions.sh +574 -0
  4. package/.claude-template/settings.template.json +26 -0
  5. package/.pi-template/extensions/n-rules-adr/docs/index.md +28 -0
  6. package/.pi-template/extensions/n-rules-adr/index.ts +105 -0
  7. package/.pi-template/extensions/n-rules-adr/tsconfig.json +17 -0
  8. package/AGENTS.template.md +53 -0
  9. package/CHANGELOG.md +4277 -0
  10. package/README.md +189 -0
  11. package/bin/docs/n-rules.md +612 -0
  12. package/bin/docs/rename-yaml-extensions.md +207 -0
  13. package/bin/n-rules.js +1709 -0
  14. package/bin/rename-yaml-extensions.mjs +42 -0
  15. package/docs/index.md +12 -0
  16. package/docs/stryker.config.md +31 -0
  17. package/docs/vitest.config.md +36 -0
  18. package/github-actions/release/action.yml +9 -0
  19. package/github-actions/setup-bun-deps/action.yml +27 -0
  20. package/package.json +87 -0
  21. package/rules/abie/base_deployment_preem/base_deployment_preem.mdc +22 -0
  22. package/rules/abie/base_deployment_preem/base_deployment_preem.rego +54 -0
  23. package/rules/abie/base_deployment_preem/concern.json +8 -0
  24. package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +19 -0
  25. package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +81 -0
  26. package/rules/abie/clean_merged_ignore_branches/concern.json +8 -0
  27. package/rules/abie/clean_merged_ignore_branches/template/clean-merged-branch.yml.snippet.yml +9 -0
  28. package/rules/abie/docs/index.md +11 -0
  29. package/rules/abie/env_dns/concern.json +4 -0
  30. package/rules/abie/env_dns/docs/main.md +32 -0
  31. package/rules/abie/env_dns/env_dns.mdc +33 -0
  32. package/rules/abie/env_dns/main.mjs +47 -0
  33. package/rules/abie/firebase_hosting/concern.json +4 -0
  34. package/rules/abie/firebase_hosting/docs/main.md +41 -0
  35. package/rules/abie/firebase_hosting/firebase_hosting.mdc +3 -0
  36. package/rules/abie/firebase_hosting/main.mjs +46 -0
  37. package/rules/abie/hc_pairing/concern.json +4 -0
  38. package/rules/abie/hc_pairing/docs/main.md +34 -0
  39. package/rules/abie/hc_pairing/hc_pairing.mdc +23 -0
  40. package/rules/abie/hc_pairing/main.mjs +52 -0
  41. package/rules/abie/health_check_policy/concern.json +8 -0
  42. package/rules/abie/health_check_policy/health_check_policy.mdc +19 -0
  43. package/rules/abie/health_check_policy/health_check_policy.rego +172 -0
  44. package/rules/abie/http_route_base/concern.json +8 -0
  45. package/rules/abie/http_route_base/http_route_base.mdc +9 -0
  46. package/rules/abie/http_route_base/http_route_base.rego +45 -0
  47. package/rules/abie/lib/docs/enabled.md +38 -0
  48. package/rules/abie/lib/docs/env-dns.md +31 -0
  49. package/rules/abie/lib/docs/hc-yaml.md +33 -0
  50. package/rules/abie/lib/docs/http-route.md +31 -0
  51. package/rules/abie/lib/docs/index.md +18 -0
  52. package/rules/abie/lib/docs/k8s-tree.md +44 -0
  53. package/rules/abie/lib/docs/kustomization-patches.md +37 -0
  54. package/rules/abie/lib/docs/overlay-paths.md +42 -0
  55. package/rules/abie/lib/docs/yaml.md +33 -0
  56. package/rules/abie/lib/enabled.mjs +37 -0
  57. package/rules/abie/lib/env-dns.mjs +81 -0
  58. package/rules/abie/lib/hc-yaml.mjs +27 -0
  59. package/rules/abie/lib/http-route.mjs +100 -0
  60. package/rules/abie/lib/k8s-tree.mjs +110 -0
  61. package/rules/abie/lib/kustomization-patches.mjs +211 -0
  62. package/rules/abie/lib/overlay-paths.mjs +97 -0
  63. package/rules/abie/lib/yaml.mjs +72 -0
  64. package/rules/abie/main.json +1 -0
  65. package/rules/abie/main.mdc +47 -0
  66. package/rules/abie/package_json_shared/concern.json +11 -0
  67. package/rules/abie/package_json_shared/package_json_shared.mdc +17 -0
  68. package/rules/abie/package_json_shared/package_json_shared.rego +16 -0
  69. package/rules/abie/ua_http_route/concern.json +4 -0
  70. package/rules/abie/ua_http_route/docs/main.md +44 -0
  71. package/rules/abie/ua_http_route/main.mjs +80 -0
  72. package/rules/abie/ua_http_route/ua_http_route.mdc +47 -0
  73. package/rules/abie/ua_node_selector/concern.json +4 -0
  74. package/rules/abie/ua_node_selector/docs/main.md +34 -0
  75. package/rules/abie/ua_node_selector/main.mjs +62 -0
  76. package/rules/abie/ua_node_selector/ua_node_selector.mdc +27 -0
  77. package/rules/adr/docs/index.md +11 -0
  78. package/rules/adr/hooks/concern.json +4 -0
  79. package/rules/adr/hooks/docs/main.md +38 -0
  80. package/rules/adr/hooks/hooks.mdc +32 -0
  81. package/rules/adr/hooks/main.mjs +367 -0
  82. package/rules/adr/main.json +1 -0
  83. package/rules/adr/main.mdc +93 -0
  84. package/rules/adr/settings_json/concern.json +9 -0
  85. package/rules/adr/settings_json/settings_json.mdc +7 -0
  86. package/rules/adr/settings_json/settings_json.rego +37 -0
  87. package/rules/adr/settings_local_json/concern.json +9 -0
  88. package/rules/adr/settings_local_json/settings_local_json.mdc +7 -0
  89. package/rules/adr/settings_local_json/settings_local_json.rego +40 -0
  90. package/rules/bun/bunfig/bunfig.mdc +12 -0
  91. package/rules/bun/bunfig/bunfig.rego +29 -0
  92. package/rules/bun/bunfig/concern.json +9 -0
  93. package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +2 -0
  94. package/rules/bun/docs/index.md +11 -0
  95. package/rules/bun/layout/concern.json +16 -0
  96. package/rules/bun/layout/docs/fix-layout.md +29 -0
  97. package/rules/bun/layout/docs/main.md +34 -0
  98. package/rules/bun/layout/fix-layout.mjs +63 -0
  99. package/rules/bun/layout/layout.mdc +60 -0
  100. package/rules/bun/layout/main.mjs +53 -0
  101. package/rules/bun/licensee/concern.json +7 -0
  102. package/rules/bun/licensee/docs/fix-licensee.md +28 -0
  103. package/rules/bun/licensee/docs/index.md +12 -0
  104. package/rules/bun/licensee/docs/main.md +37 -0
  105. package/rules/bun/licensee/fix-licensee.mjs +32 -0
  106. package/rules/bun/licensee/main.mjs +44 -0
  107. package/rules/bun/main.json +1 -0
  108. package/rules/bun/main.mdc +11 -0
  109. package/rules/bun/package_json/concern.json +9 -0
  110. package/rules/bun/package_json/docs/fix-package_json.md +28 -0
  111. package/rules/bun/package_json/docs/index.md +9 -0
  112. package/rules/bun/package_json/fix-package_json.mjs +311 -0
  113. package/rules/bun/package_json/package_json.mdc +14 -0
  114. package/rules/bun/package_json/package_json.rego +64 -0
  115. package/rules/bun/package_json/template/package.json.deny.json +4 -0
  116. package/rules/capacitor/docs/index.md +11 -0
  117. package/rules/capacitor/main.json +1 -0
  118. package/rules/capacitor/main.mdc +12 -0
  119. package/rules/capacitor/package_json/concern.json +9 -0
  120. package/rules/capacitor/package_json/package_json.mdc +9 -0
  121. package/rules/capacitor/package_json/package_json.rego +45 -0
  122. package/rules/capacitor/platforms/concern.json +4 -0
  123. package/rules/capacitor/platforms/docs/main.md +41 -0
  124. package/rules/capacitor/platforms/main.mjs +486 -0
  125. package/rules/changelog/consistency/concern.json +4 -0
  126. package/rules/changelog/consistency/docs/fix-consistency.md +31 -0
  127. package/rules/changelog/consistency/docs/main.md +41 -0
  128. package/rules/changelog/consistency/fix-consistency.mjs +71 -0
  129. package/rules/changelog/consistency/main.mjs +820 -0
  130. package/rules/changelog/docs/index.md +11 -0
  131. package/rules/changelog/lib/docs/index.md +11 -0
  132. package/rules/changelog/lib/docs/package-manifest.md +214 -0
  133. package/rules/changelog/lib/package-manifest.mjs +158 -0
  134. package/rules/changelog/main.json +1 -0
  135. package/rules/changelog/main.mdc +7 -0
  136. package/rules/changelog/presence/concern.json +7 -0
  137. package/rules/changelog/presence/docs/main.md +44 -0
  138. package/rules/changelog/presence/main.mjs +87 -0
  139. package/rules/ci4/docs/index.md +11 -0
  140. package/rules/ci4/main.json +1 -0
  141. package/rules/ci4/main.mdc +375 -0
  142. package/rules/ci4/marksman_config/concern.json +5 -0
  143. package/rules/ci4/marksman_config/data/marksman_config/marksman.baseline.toml +27 -0
  144. package/rules/ci4/marksman_config/docs/fix-marksman_config.md +27 -0
  145. package/rules/ci4/marksman_config/docs/main.md +30 -0
  146. package/rules/ci4/marksman_config/fix-marksman_config.mjs +24 -0
  147. package/rules/ci4/marksman_config/main.mjs +38 -0
  148. package/rules/ci4/marksman_config/marksman_config.mdc +31 -0
  149. package/rules/ci4/vscode_extensions/concern.json +9 -0
  150. package/rules/ci4/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  151. package/rules/ci4/vscode_extensions/docs/index.md +11 -0
  152. package/rules/ci4/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  153. package/rules/ci4/vscode_extensions/template/extensions.json.snippet.json +3 -0
  154. package/rules/ci4/vscode_extensions/vscode_extensions.mdc +9 -0
  155. package/rules/ci4/vscode_extensions/vscode_extensions.rego +12 -0
  156. package/rules/doc-files/check/concern.json +7 -0
  157. package/rules/doc-files/check/docs/fix-check.md +28 -0
  158. package/rules/doc-files/check/docs/fix-worker.md +28 -0
  159. package/rules/doc-files/check/docs/main.md +32 -0
  160. package/rules/doc-files/check/fix-check.mjs +45 -0
  161. package/rules/doc-files/check/fix-worker.mjs +56 -0
  162. package/rules/doc-files/check/main.mjs +99 -0
  163. package/rules/doc-files/docgen-crc/concern.json +3 -0
  164. package/rules/doc-files/docgen-crc/docs/main.md +46 -0
  165. package/rules/doc-files/docgen-crc/main.mjs +207 -0
  166. package/rules/doc-files/docgen-extract/concern.json +3 -0
  167. package/rules/doc-files/docgen-extract/docs/main.md +38 -0
  168. package/rules/doc-files/docgen-extract/main.mjs +471 -0
  169. package/rules/doc-files/docgen-extract-anchors/concern.json +3 -0
  170. package/rules/doc-files/docgen-extract-anchors/docs/main.md +49 -0
  171. package/rules/doc-files/docgen-extract-anchors/main.mjs +115 -0
  172. package/rules/doc-files/docgen-files-batch/concern.json +3 -0
  173. package/rules/doc-files/docgen-files-batch/docs/main.md +38 -0
  174. package/rules/doc-files/docgen-files-batch/main.mjs +517 -0
  175. package/rules/doc-files/docgen-fix-worker/concern.json +3 -0
  176. package/rules/doc-files/docgen-gen/concern.json +3 -0
  177. package/rules/doc-files/docgen-gen/docs/main.md +40 -0
  178. package/rules/doc-files/docgen-gen/main.mjs +582 -0
  179. package/rules/doc-files/docgen-ignore/concern.json +3 -0
  180. package/rules/doc-files/docgen-ignore/docs/main.md +33 -0
  181. package/rules/doc-files/docgen-ignore/main.mjs +54 -0
  182. package/rules/doc-files/docgen-judge/concern.json +3 -0
  183. package/rules/doc-files/docgen-judge/docs/main.md +43 -0
  184. package/rules/doc-files/docgen-judge/main.mjs +116 -0
  185. package/rules/doc-files/docgen-prompts/concern.json +3 -0
  186. package/rules/doc-files/docgen-prompts/docs/main.md +48 -0
  187. package/rules/doc-files/docgen-prompts/main.mjs +222 -0
  188. package/rules/doc-files/docgen-scan/concern.json +3 -0
  189. package/rules/doc-files/docgen-scan/docs/main.md +52 -0
  190. package/rules/doc-files/docgen-scan/main.mjs +231 -0
  191. package/rules/doc-files/docs/index.md +11 -0
  192. package/rules/doc-files/main.json +1 -0
  193. package/rules/doc-files/main.mdc +49 -0
  194. package/rules/doc-files/units/concern.json +3 -0
  195. package/rules/doc-files/units/docs/main.md +32 -0
  196. package/rules/doc-files/units/main.mjs +20 -0
  197. package/rules/doc-files/units-js/concern.json +3 -0
  198. package/rules/doc-files/units-js/docs/main.md +32 -0
  199. package/rules/doc-files/units-js/main.mjs +141 -0
  200. package/rules/doc-files/units-rs/concern.json +3 -0
  201. package/rules/doc-files/units-rs/docs/main.md +36 -0
  202. package/rules/doc-files/units-rs/main.mjs +311 -0
  203. package/rules/docker/docs/index.md +11 -0
  204. package/rules/docker/lib/docker-hadolint.mjs +60 -0
  205. package/rules/docker/lib/docker-mirror.mjs +148 -0
  206. package/rules/docker/lib/docker-native-addon.mjs +93 -0
  207. package/rules/docker/lib/docker-nginx-user.mjs +122 -0
  208. package/rules/docker/lib/docs/docker-hadolint.md +29 -0
  209. package/rules/docker/lib/docs/docker-mirror.md +251 -0
  210. package/rules/docker/lib/docs/docker-native-addon.md +174 -0
  211. package/rules/docker/lib/docs/docker-nginx-user.md +223 -0
  212. package/rules/docker/lib/docs/index.md +14 -0
  213. package/rules/docker/lint/concern.json +7 -0
  214. package/rules/docker/lint/docs/main.md +47 -0
  215. package/rules/docker/lint/main.mjs +360 -0
  216. package/rules/docker/lint_docker_yml/concern.json +9 -0
  217. package/rules/docker/lint_docker_yml/lint_docker_yml.mdc +14 -0
  218. package/rules/docker/lint_docker_yml/lint_docker_yml.rego +79 -0
  219. package/rules/docker/lint_docker_yml/template/lint-docker.yml.snippet.yml +41 -0
  220. package/rules/docker/main.json +1 -0
  221. package/rules/docker/main.mdc +14 -0
  222. package/rules/efes/docs/index.md +11 -0
  223. package/rules/efes/main.json +1 -0
  224. package/rules/efes/main.mdc +21 -0
  225. package/rules/efes/package_json_shared/concern.json +11 -0
  226. package/rules/efes/package_json_shared/package_json_shared.mdc +33 -0
  227. package/rules/efes/package_json_shared/package_json_shared.rego +16 -0
  228. package/rules/feedback/docs/index.md +11 -0
  229. package/rules/feedback/main.json +1 -0
  230. package/rules/feedback/main.mdc +63 -0
  231. package/rules/ga/clean_ga_workflows/clean_ga_workflows.mdc +20 -0
  232. package/rules/ga/clean_ga_workflows/clean_ga_workflows.rego +112 -0
  233. package/rules/ga/clean_ga_workflows/concern.json +10 -0
  234. package/rules/ga/clean_ga_workflows/template/clean-ga-workflows.yml.snippet.yml +26 -0
  235. package/rules/ga/clean_merged_branch/clean_merged_branch.mdc +24 -0
  236. package/rules/ga/clean_merged_branch/clean_merged_branch.rego +163 -0
  237. package/rules/ga/clean_merged_branch/concern.json +10 -0
  238. package/rules/ga/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +37 -0
  239. package/rules/ga/docs/index.md +11 -0
  240. package/rules/ga/git_ai/concern.json +11 -0
  241. package/rules/ga/git_ai/git_ai.mdc +19 -0
  242. package/rules/ga/git_ai/git_ai.rego +76 -0
  243. package/rules/ga/git_ai/template/git-ai.yml.snippet.yml +30 -0
  244. package/rules/ga/lint_ga/concern.json +10 -0
  245. package/rules/ga/lint_ga/lint_ga.mdc +21 -0
  246. package/rules/ga/lint_ga/lint_ga.rego +132 -0
  247. package/rules/ga/lint_ga/template/lint-ga.yml.snippet.yml +41 -0
  248. package/rules/ga/main.json +1 -0
  249. package/rules/ga/main.mdc +17 -0
  250. package/rules/ga/vscode_extensions/concern.json +11 -0
  251. package/rules/ga/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  252. package/rules/ga/vscode_extensions/docs/index.md +11 -0
  253. package/rules/ga/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  254. package/rules/ga/vscode_extensions/template/extensions.json.snippet.json +1 -0
  255. package/rules/ga/vscode_extensions/vscode_extensions.mdc +9 -0
  256. package/rules/ga/vscode_extensions/vscode_extensions.rego +18 -0
  257. package/rules/ga/vscode_settings/concern.json +11 -0
  258. package/rules/ga/vscode_settings/template/settings.json.snippet.json +1 -0
  259. package/rules/ga/vscode_settings/vscode_settings.mdc +9 -0
  260. package/rules/ga/vscode_settings/vscode_settings.rego +22 -0
  261. package/rules/ga/workflow_common/concern.json +9 -0
  262. package/rules/ga/workflow_common/template/uses-min-versions.snippet.json +4 -0
  263. package/rules/ga/workflow_common/workflow_common.mdc +18 -0
  264. package/rules/ga/workflow_common/workflow_common.rego +288 -0
  265. package/rules/ga/workflows/concern.json +8 -0
  266. package/rules/ga/workflows/docs/fix-workflows.md +37 -0
  267. package/rules/ga/workflows/docs/main.md +38 -0
  268. package/rules/ga/workflows/fix-workflows.mjs +212 -0
  269. package/rules/ga/workflows/main.mjs +433 -0
  270. package/rules/ga/workflows/workflows.mdc +33 -0
  271. package/rules/ga/zizmor_yml/concern.json +11 -0
  272. package/rules/ga/zizmor_yml/template/zizmor.yml.snippet.yml +5 -0
  273. package/rules/ga/zizmor_yml/zizmor_yml.mdc +9 -0
  274. package/rules/ga/zizmor_yml/zizmor_yml.rego +27 -0
  275. package/rules/graphql/docs/index.md +11 -0
  276. package/rules/graphql/lib/docs/graphql-gql-scan.md +226 -0
  277. package/rules/graphql/lib/docs/index.md +11 -0
  278. package/rules/graphql/lib/graphql-gql-scan.mjs +146 -0
  279. package/rules/graphql/main.json +1 -0
  280. package/rules/graphql/main.mdc +8 -0
  281. package/rules/graphql/tooling/concern.json +8 -0
  282. package/rules/graphql/tooling/docs/main.md +36 -0
  283. package/rules/graphql/tooling/main.mjs +129 -0
  284. package/rules/graphql/tooling/tooling.mdc +13 -0
  285. package/rules/graphql/vscode_extensions/concern.json +9 -0
  286. package/rules/graphql/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
  287. package/rules/graphql/vscode_extensions/docs/index.md +11 -0
  288. package/rules/graphql/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  289. package/rules/graphql/vscode_extensions/vscode_extensions.mdc +9 -0
  290. package/rules/graphql/vscode_extensions/vscode_extensions.rego +20 -0
  291. package/rules/hasura/docs/index.md +11 -0
  292. package/rules/hasura/internal_urls/concern.json +5 -0
  293. package/rules/hasura/internal_urls/docs/fix-internal_urls.md +26 -0
  294. package/rules/hasura/internal_urls/docs/index.md +12 -0
  295. package/rules/hasura/internal_urls/docs/main.md +36 -0
  296. package/rules/hasura/internal_urls/fix-internal_urls.mjs +66 -0
  297. package/rules/hasura/internal_urls/internal_urls.mdc +27 -0
  298. package/rules/hasura/internal_urls/main.mjs +233 -0
  299. package/rules/hasura/main.json +1 -0
  300. package/rules/hasura/main.mdc +8 -0
  301. package/rules/hasura/migrations/concern.json +4 -0
  302. package/rules/hasura/migrations/docs/fix-migrations.md +25 -0
  303. package/rules/hasura/migrations/docs/index.md +12 -0
  304. package/rules/hasura/migrations/docs/main.md +35 -0
  305. package/rules/hasura/migrations/fix-migrations.mjs +35 -0
  306. package/rules/hasura/migrations/main.mjs +53 -0
  307. package/rules/hasura/migrations/migrations.mdc +13 -0
  308. package/rules/hasura/svc_hl/concern.json +8 -0
  309. package/rules/hasura/svc_hl/svc_hl.mdc +15 -0
  310. package/rules/hasura/svc_hl/svc_hl.rego +50 -0
  311. package/rules/image-avif/avif_generation/avif_generation.mdc +26 -0
  312. package/rules/image-avif/avif_generation/concern.json +4 -0
  313. package/rules/image-avif/avif_generation/docs/fix-avif_generation.md +27 -0
  314. package/rules/image-avif/avif_generation/docs/main.md +36 -0
  315. package/rules/image-avif/avif_generation/fix-avif_generation.mjs +80 -0
  316. package/rules/image-avif/avif_generation/main.mjs +411 -0
  317. package/rules/image-avif/docs/index.md +11 -0
  318. package/rules/image-avif/main.json +1 -0
  319. package/rules/image-avif/main.mdc +8 -0
  320. package/rules/image-avif/package_json/concern.json +9 -0
  321. package/rules/image-avif/package_json/package_json.mdc +18 -0
  322. package/rules/image-avif/package_json/package_json.rego +47 -0
  323. package/rules/image-avif/package_json/template/package.json.deny.json +5 -0
  324. package/rules/image-compress/check/concern.json +7 -0
  325. package/rules/image-compress/check/docs/fix-check.md +34 -0
  326. package/rules/image-compress/check/docs/index.md +10 -0
  327. package/rules/image-compress/check/docs/main.md +31 -0
  328. package/rules/image-compress/check/fix-check.mjs +74 -0
  329. package/rules/image-compress/check/main.mjs +64 -0
  330. package/rules/image-compress/docs/index.md +11 -0
  331. package/rules/image-compress/main.json +1 -0
  332. package/rules/image-compress/main.mdc +10 -0
  333. package/rules/image-compress/package_json/concern.json +9 -0
  334. package/rules/image-compress/package_json/package_json.mdc +13 -0
  335. package/rules/image-compress/package_json/package_json.rego +21 -0
  336. package/rules/image-compress/package_json/template/package.json.deny.json +8 -0
  337. package/rules/image-compress/package_setup/concern.json +4 -0
  338. package/rules/image-compress/package_setup/docs/main.md +34 -0
  339. package/rules/image-compress/package_setup/main.mjs +98 -0
  340. package/rules/image-compress/package_setup/package_setup.mdc +13 -0
  341. package/rules/js/check/concern.json +19 -0
  342. package/rules/js/check/docs/eslint-config.md +56 -0
  343. package/rules/js/check/docs/fix-check.md +31 -0
  344. package/rules/js/check/docs/index.md +13 -0
  345. package/rules/js/check/docs/main.md +45 -0
  346. package/rules/js/check/eslint-config.mjs +262 -0
  347. package/rules/js/check/fix-check.mjs +39 -0
  348. package/rules/js/check/main.mjs +312 -0
  349. package/rules/js/dep-policy/concern.json +4 -0
  350. package/rules/js/dep-policy/dep-policy.mdc +36 -0
  351. package/rules/js/dep-policy/docs/main.md +35 -0
  352. package/rules/js/dep-policy/main.mjs +99 -0
  353. package/rules/js/docs/index.md +11 -0
  354. package/rules/js/eslint/concern.json +7 -0
  355. package/rules/js/eslint/docs/fix-eslint.md +32 -0
  356. package/rules/js/eslint/docs/main.md +33 -0
  357. package/rules/js/eslint/fix-eslint.mjs +77 -0
  358. package/rules/js/eslint/main.mjs +99 -0
  359. package/rules/js/jscpd_config/concern.json +11 -0
  360. package/rules/js/jscpd_config/jscpd_config.mdc +14 -0
  361. package/rules/js/jscpd_config/jscpd_config.rego +44 -0
  362. package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +7 -0
  363. package/rules/js/jscpd_duplicates/concern.json +7 -0
  364. package/rules/js/jscpd_duplicates/docs/main.md +29 -0
  365. package/rules/js/jscpd_duplicates/main.mjs +70 -0
  366. package/rules/js/knip/concern.json +6 -0
  367. package/rules/js/knip/docs/main.md +32 -0
  368. package/rules/js/knip/main.mjs +68 -0
  369. package/rules/js/lint-findings/concern.json +3 -0
  370. package/rules/js/lint-findings/docs/main.md +41 -0
  371. package/rules/js/lint-findings/main.mjs +125 -0
  372. package/rules/js/lint_js_yml/concern.json +9 -0
  373. package/rules/js/lint_js_yml/lint_js_yml.mdc +14 -0
  374. package/rules/js/lint_js_yml/lint_js_yml.rego +117 -0
  375. package/rules/js/lint_js_yml/template/lint-js.yml.snippet.yml +40 -0
  376. package/rules/js/main.json +1 -0
  377. package/rules/js/main.mdc +19 -0
  378. package/rules/js/package_json/concern.json +9 -0
  379. package/rules/js/package_json/package_json.mdc +15 -0
  380. package/rules/js/package_json/package_json.rego +142 -0
  381. package/rules/js/package_json/template/package.json.snippet.json +6 -0
  382. package/rules/js/tooling/concern.json +3 -0
  383. package/rules/js/tooling/data/tooling/knip-canonical.json +29 -0
  384. package/rules/js/tooling/data/tooling/oxlint-canonical.json +400 -0
  385. package/rules/js/tooling/docs/main.md +31 -0
  386. package/rules/js/tooling/main.mjs +149 -0
  387. package/rules/js/utils_imports/concern.json +4 -0
  388. package/rules/js/utils_imports/docs/main.md +50 -0
  389. package/rules/js/utils_imports/main.mjs +185 -0
  390. package/rules/js/vscode_extensions/concern.json +11 -0
  391. package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  392. package/rules/js/vscode_extensions/docs/index.md +11 -0
  393. package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  394. package/rules/js/vscode_extensions/template/extensions.json.snippet.json +3 -0
  395. package/rules/js/vscode_extensions/vscode_extensions.mdc +11 -0
  396. package/rules/js/vscode_extensions/vscode_extensions.rego +12 -0
  397. package/rules/js-bun-db/docs/index.md +11 -0
  398. package/rules/js-bun-db/lib/bun-sql-scan.mjs +1055 -0
  399. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +63 -0
  400. package/rules/js-bun-db/lib/docs/index.md +11 -0
  401. package/rules/js-bun-db/main.json +1 -0
  402. package/rules/js-bun-db/main.mdc +8 -0
  403. package/rules/js-bun-db/package_json/concern.json +9 -0
  404. package/rules/js-bun-db/package_json/package_json.mdc +17 -0
  405. package/rules/js-bun-db/package_json/package_json.rego +15 -0
  406. package/rules/js-bun-db/package_json/template/package.json.deny.json +6 -0
  407. package/rules/js-bun-db/safety/concern.json +4 -0
  408. package/rules/js-bun-db/safety/docs/main.md +34 -0
  409. package/rules/js-bun-db/safety/main.mjs +430 -0
  410. package/rules/js-bun-redis/docs/index.md +11 -0
  411. package/rules/js-bun-redis/imports/concern.json +4 -0
  412. package/rules/js-bun-redis/imports/docs/main.md +36 -0
  413. package/rules/js-bun-redis/imports/imports.mdc +47 -0
  414. package/rules/js-bun-redis/imports/main.mjs +88 -0
  415. package/rules/js-bun-redis/lib/docs/index.md +11 -0
  416. package/rules/js-bun-redis/lib/docs/redis-imports.md +227 -0
  417. package/rules/js-bun-redis/lib/redis-imports.mjs +130 -0
  418. package/rules/js-bun-redis/main.json +1 -0
  419. package/rules/js-bun-redis/main.mdc +8 -0
  420. package/rules/js-bun-redis/package_json/concern.json +9 -0
  421. package/rules/js-bun-redis/package_json/package_json.mdc +11 -0
  422. package/rules/js-bun-redis/package_json/package_json.rego +15 -0
  423. package/rules/js-bun-redis/package_json/template/package.json.deny.json +12 -0
  424. package/rules/js-mssql/deps/concern.json +4 -0
  425. package/rules/js-mssql/deps/docs/main.md +33 -0
  426. package/rules/js-mssql/deps/main.mjs +297 -0
  427. package/rules/js-mssql/docs/index.md +11 -0
  428. package/rules/js-mssql/lib/docs/index.md +11 -0
  429. package/rules/js-mssql/lib/docs/mssql-pool-scan.md +380 -0
  430. package/rules/js-mssql/lib/mssql-pool-scan.mjs +610 -0
  431. package/rules/js-mssql/main.json +1 -0
  432. package/rules/js-mssql/main.mdc +14 -0
  433. package/rules/js-mssql/package_json/concern.json +9 -0
  434. package/rules/js-mssql/package_json/package_json.mdc +9 -0
  435. package/rules/js-mssql/package_json/package_json.rego +57 -0
  436. package/rules/js-run/configmap/concern.json +9 -0
  437. package/rules/js-run/configmap/configmap.mdc +31 -0
  438. package/rules/js-run/configmap/configmap.rego +21 -0
  439. package/rules/js-run/configmap/template/configmap.yaml.contains.yml +4 -0
  440. package/rules/js-run/docs/index.md +11 -0
  441. package/rules/js-run/jsconfig/concern.json +9 -0
  442. package/rules/js-run/jsconfig/docs/fix-jsconfig.md +29 -0
  443. package/rules/js-run/jsconfig/docs/index.md +9 -0
  444. package/rules/js-run/jsconfig/fix-jsconfig.mjs +119 -0
  445. package/rules/js-run/jsconfig/jsconfig.mdc +25 -0
  446. package/rules/js-run/jsconfig/jsconfig.rego +59 -0
  447. package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +10 -0
  448. package/rules/js-run/lib/bunyan-imports.mjs +98 -0
  449. package/rules/js-run/lib/check-env-scan.mjs +338 -0
  450. package/rules/js-run/lib/conn-file-rules.mjs +214 -0
  451. package/rules/js-run/lib/conn-imports-scan.mjs +154 -0
  452. package/rules/js-run/lib/docs/bunyan-imports.md +121 -0
  453. package/rules/js-run/lib/docs/check-env-scan.md +438 -0
  454. package/rules/js-run/lib/docs/conn-file-rules.md +304 -0
  455. package/rules/js-run/lib/docs/conn-imports-scan.md +208 -0
  456. package/rules/js-run/lib/docs/index.md +16 -0
  457. package/rules/js-run/lib/docs/promise-settimeout-scan.md +334 -0
  458. package/rules/js-run/lib/docs/temporal-scan.md +29 -0
  459. package/rules/js-run/lib/promise-settimeout-scan.mjs +128 -0
  460. package/rules/js-run/lib/temporal-scan.mjs +52 -0
  461. package/rules/js-run/main.json +1 -0
  462. package/rules/js-run/main.mdc +16 -0
  463. package/rules/js-run/package_json/concern.json +9 -0
  464. package/rules/js-run/package_json/package_json.mdc +38 -0
  465. package/rules/js-run/package_json/package_json.rego +37 -0
  466. package/rules/js-run/package_json/template/package.json.deny.json +22 -0
  467. package/rules/js-run/runtime/concern.json +12 -0
  468. package/rules/js-run/runtime/docs/fix-runtime.md +27 -0
  469. package/rules/js-run/runtime/docs/main.md +35 -0
  470. package/rules/js-run/runtime/fix-runtime.mjs +46 -0
  471. package/rules/js-run/runtime/main.mjs +494 -0
  472. package/rules/js-run/runtime/runtime.mdc +14 -0
  473. package/rules/k8s/base_kustomization/base_kustomization.mdc +12 -0
  474. package/rules/k8s/base_kustomization/base_kustomization.rego +77 -0
  475. package/rules/k8s/base_kustomization/concern.json +8 -0
  476. package/rules/k8s/base_manifest/base_manifest.mdc +14 -0
  477. package/rules/k8s/base_manifest/base_manifest.rego +154 -0
  478. package/rules/k8s/base_manifest/concern.json +8 -0
  479. package/rules/k8s/docs/index.md +11 -0
  480. package/rules/k8s/gateway/concern.json +8 -0
  481. package/rules/k8s/gateway/gateway.mdc +31 -0
  482. package/rules/k8s/gateway/gateway.rego +151 -0
  483. package/rules/k8s/hasura_configmap/concern.json +8 -0
  484. package/rules/k8s/hasura_configmap/hasura_configmap.mdc +20 -0
  485. package/rules/k8s/hasura_configmap/hasura_configmap.rego +129 -0
  486. package/rules/k8s/hasura_httproute/concern.json +8 -0
  487. package/rules/k8s/hasura_httproute/hasura_httproute.mdc +16 -0
  488. package/rules/k8s/hasura_httproute/hasura_httproute.rego +298 -0
  489. package/rules/k8s/hpa_pdb/concern.json +8 -0
  490. package/rules/k8s/hpa_pdb/hpa_pdb.mdc +25 -0
  491. package/rules/k8s/hpa_pdb/hpa_pdb.rego +139 -0
  492. package/rules/k8s/kubeconform/concern.json +7 -0
  493. package/rules/k8s/kubeconform/docs/main.md +32 -0
  494. package/rules/k8s/kubeconform/main.mjs +39 -0
  495. package/rules/k8s/kustomization/concern.json +8 -0
  496. package/rules/k8s/kustomization/kustomization.mdc +20 -0
  497. package/rules/k8s/kustomization/kustomization.rego +220 -0
  498. package/rules/k8s/lint_k8s_yml/concern.json +9 -0
  499. package/rules/k8s/lint_k8s_yml/lint_k8s_yml.rego +57 -0
  500. package/rules/k8s/lint_k8s_yml/template/lint-k8s.yml.snippet.yml +43 -0
  501. package/rules/k8s/main.json +1 -0
  502. package/rules/k8s/main.mdc +22 -0
  503. package/rules/k8s/manifest/concern.json +8 -0
  504. package/rules/k8s/manifest/manifest.mdc +17 -0
  505. package/rules/k8s/manifest/manifest.rego +328 -0
  506. package/rules/k8s/manifests/concern.json +6 -0
  507. package/rules/k8s/manifests/docs/fix-manifests.md +47 -0
  508. package/rules/k8s/manifests/fix-manifests.mjs +217 -0
  509. package/rules/k8s/manifests/main.mjs +6838 -0
  510. package/rules/k8s/network_policy/concern.json +8 -0
  511. package/rules/k8s/network_policy/network_policy.mdc +22 -0
  512. package/rules/k8s/network_policy/network_policy.rego +151 -0
  513. package/rules/k8s/network_policy/template/deployment.snippet.yaml +61 -0
  514. package/rules/k8s/network_policy/template/stateful-set.snippet.yaml +69 -0
  515. package/rules/k8s/svc_hl_yaml/concern.json +8 -0
  516. package/rules/k8s/svc_hl_yaml/svc_hl_yaml.mdc +13 -0
  517. package/rules/k8s/svc_hl_yaml/svc_hl_yaml.rego +51 -0
  518. package/rules/k8s/svc_yaml/concern.json +8 -0
  519. package/rules/k8s/svc_yaml/svc_yaml.mdc +12 -0
  520. package/rules/k8s/svc_yaml/svc_yaml.rego +31 -0
  521. package/rules/nginx-default-tpl/docs/index.md +11 -0
  522. package/rules/nginx-default-tpl/main.json +1 -0
  523. package/rules/nginx-default-tpl/main.mdc +8 -0
  524. package/rules/nginx-default-tpl/template/concern.json +17 -0
  525. package/rules/nginx-default-tpl/template/docs/fix-template.md +26 -0
  526. package/rules/nginx-default-tpl/template/docs/main.md +42 -0
  527. package/rules/nginx-default-tpl/template/fix-template.mjs +67 -0
  528. package/rules/nginx-default-tpl/template/main.mjs +505 -0
  529. package/rules/nginx-default-tpl/vscode_extensions/concern.json +9 -0
  530. package/rules/nginx-default-tpl/vscode_extensions/vscode_extensions.mdc +11 -0
  531. package/rules/nginx-default-tpl/vscode_extensions/vscode_extensions.rego +16 -0
  532. package/rules/nginx-default-tpl/vscode_settings/concern.json +9 -0
  533. package/rules/nginx-default-tpl/vscode_settings/vscode_settings.mdc +15 -0
  534. package/rules/nginx-default-tpl/vscode_settings/vscode_settings.rego +36 -0
  535. package/rules/npm-module/docs/index.md +11 -0
  536. package/rules/npm-module/emit_types_config/concern.json +9 -0
  537. package/rules/npm-module/emit_types_config/emit_types_config.mdc +43 -0
  538. package/rules/npm-module/emit_types_config/emit_types_config.rego +28 -0
  539. package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +9 -0
  540. package/rules/npm-module/header_doc_pointer/concern.json +5 -0
  541. package/rules/npm-module/header_doc_pointer/docs/main.md +40 -0
  542. package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +18 -0
  543. package/rules/npm-module/header_doc_pointer/main.mjs +131 -0
  544. package/rules/npm-module/main.json +1 -0
  545. package/rules/npm-module/main.mdc +38 -0
  546. package/rules/npm-module/npm_package_json/concern.json +9 -0
  547. package/rules/npm-module/npm_package_json/npm_package_json.mdc +57 -0
  548. package/rules/npm-module/npm_package_json/npm_package_json.rego +73 -0
  549. package/rules/npm-module/npm_package_json/template/package.json.snippet.json +1 -0
  550. package/rules/npm-module/npm_publish_yml/concern.json +10 -0
  551. package/rules/npm-module/npm_publish_yml/template/npm-publish.yml.snippet.yml +49 -0
  552. package/rules/npm-module/package_structure/concern.json +5 -0
  553. package/rules/npm-module/package_structure/docs/main.md +37 -0
  554. package/rules/npm-module/package_structure/main.mjs +515 -0
  555. package/rules/npm-module/package_structure/package_structure.mdc +63 -0
  556. package/rules/npm-module/root_package_json/concern.json +9 -0
  557. package/rules/npm-module/root_package_json/root_package_json.mdc +41 -0
  558. package/rules/npm-module/root_package_json/root_package_json.rego +28 -0
  559. package/rules/npm-module/root_package_json/template/package.json.snippet.json +1 -0
  560. package/rules/npm-module/rule_meta/concern.json +8 -0
  561. package/rules/npm-module/rule_meta/docs/main.md +35 -0
  562. package/rules/npm-module/rule_meta/main.mjs +119 -0
  563. package/rules/npm-module/rule_meta/rule_meta.mdc +11 -0
  564. package/rules/npm-module/skill_meta/concern.json +5 -0
  565. package/rules/npm-module/skill_meta/docs/main.md +149 -0
  566. package/rules/npm-module/skill_meta/main.mjs +91 -0
  567. package/rules/npm-module/skill_meta/skill_meta.mdc +11 -0
  568. package/rules/php/cs_fixer/concern.json +7 -0
  569. package/rules/php/cs_fixer/docs/main.md +34 -0
  570. package/rules/php/cs_fixer/main.mjs +52 -0
  571. package/rules/php/docs/index.md +11 -0
  572. package/rules/php/lint_php_yml/concern.json +9 -0
  573. package/rules/php/lint_php_yml/lint_php_yml.mdc +23 -0
  574. package/rules/php/lint_php_yml/lint_php_yml.rego +34 -0
  575. package/rules/php/lint_php_yml/template/lint-php.yml.snippet.yml +47 -0
  576. package/rules/php/main.json +1 -0
  577. package/rules/php/main.mdc +8 -0
  578. package/rules/php/phpcs/concern.json +7 -0
  579. package/rules/php/phpcs/docs/main.md +31 -0
  580. package/rules/php/phpcs/main.mjs +71 -0
  581. package/rules/php/project/concern.json +6 -0
  582. package/rules/php/project/docs/main.md +36 -0
  583. package/rules/php/project/main.mjs +88 -0
  584. package/rules/php/tooling/concern.json +5 -0
  585. package/rules/php/tooling/docs/main.md +33 -0
  586. package/rules/php/tooling/main.mjs +35 -0
  587. package/rules/php/tooling/tooling.mdc +66 -0
  588. package/rules/python/applies/concern.json +4 -0
  589. package/rules/python/applies/docs/main.md +29 -0
  590. package/rules/python/applies/main.mjs +24 -0
  591. package/rules/python/docs/index.md +11 -0
  592. package/rules/python/lib/docs/index.md +9 -0
  593. package/rules/python/lib/docs/uv-run.md +32 -0
  594. package/rules/python/lib/uv-run.mjs +48 -0
  595. package/rules/python/lint_python_yml/concern.json +9 -0
  596. package/rules/python/lint_python_yml/lint_python_yml.mdc +12 -0
  597. package/rules/python/lint_python_yml/lint_python_yml.rego +68 -0
  598. package/rules/python/lint_python_yml/template/lint-python.yml.snippet.yml +41 -0
  599. package/rules/python/main.json +1 -0
  600. package/rules/python/main.mdc +8 -0
  601. package/rules/python/mypy/concern.json +7 -0
  602. package/rules/python/mypy/docs/main.md +32 -0
  603. package/rules/python/mypy/main.mjs +36 -0
  604. package/rules/python/project/concern.json +6 -0
  605. package/rules/python/project/docs/main.md +43 -0
  606. package/rules/python/project/main.mjs +115 -0
  607. package/rules/python/pyproject_toml/concern.json +9 -0
  608. package/rules/python/pyproject_toml/pyproject_toml.mdc +13 -0
  609. package/rules/python/pyproject_toml/pyproject_toml.rego +53 -0
  610. package/rules/python/pyproject_toml/template/pyproject.toml.deny.toml +2 -0
  611. package/rules/python/pyproject_toml/template/pyproject.toml.snippet.toml +12 -0
  612. package/rules/python/ruff/concern.json +7 -0
  613. package/rules/python/ruff/docs/fix-ruff.md +34 -0
  614. package/rules/python/ruff/docs/main.md +35 -0
  615. package/rules/python/ruff/fix-ruff.mjs +63 -0
  616. package/rules/python/ruff/main.mjs +52 -0
  617. package/rules/python/tooling/concern.json +15 -0
  618. package/rules/python/tooling/docs/index.md +11 -0
  619. package/rules/python/tooling/docs/main.md +35 -0
  620. package/rules/python/tooling/main.mjs +50 -0
  621. package/rules/python/tooling/tooling.mdc +23 -0
  622. package/rules/rego/conftest_verify/concern.json +6 -0
  623. package/rules/rego/conftest_verify/docs/main.md +31 -0
  624. package/rules/rego/conftest_verify/main.mjs +55 -0
  625. package/rules/rego/docs/index.md +11 -0
  626. package/rules/rego/lib/docs/index.md +9 -0
  627. package/rules/rego/lib/docs/run-external-tool.md +36 -0
  628. package/rules/rego/lib/run-external-tool.mjs +53 -0
  629. package/rules/rego/main.json +1 -0
  630. package/rules/rego/main.mdc +20 -0
  631. package/rules/rego/opa_check/concern.json +7 -0
  632. package/rules/rego/opa_check/docs/main.md +32 -0
  633. package/rules/rego/opa_check/main.mjs +34 -0
  634. package/rules/rego/package_json/concern.json +10 -0
  635. package/rules/rego/package_json/package_json.mdc +12 -0
  636. package/rules/rego/package_json/package_json.rego +21 -0
  637. package/rules/rego/regal/concern.json +7 -0
  638. package/rules/rego/regal/docs/index.md +11 -0
  639. package/rules/rego/regal/docs/main.md +32 -0
  640. package/rules/rego/regal/main.mjs +34 -0
  641. package/rules/rego/tooling/concern.json +5 -0
  642. package/rules/rego/tooling/docs/index.md +11 -0
  643. package/rules/rego/tooling/docs/main.md +31 -0
  644. package/rules/rego/tooling/main.mjs +25 -0
  645. package/rules/rego/tooling/tooling.mdc +14 -0
  646. package/rules/rego/vscode_extensions/concern.json +11 -0
  647. package/rules/rego/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
  648. package/rules/rego/vscode_extensions/docs/index.md +11 -0
  649. package/rules/rego/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  650. package/rules/rego/vscode_extensions/template/extensions.json.snippet.json +1 -0
  651. package/rules/rego/vscode_extensions/vscode_extensions.mdc +11 -0
  652. package/rules/rego/vscode_extensions/vscode_extensions.rego +15 -0
  653. package/rules/rego/vscode_settings/concern.json +11 -0
  654. package/rules/rego/vscode_settings/template/settings.json.snippet.json +6 -0
  655. package/rules/rego/vscode_settings/vscode_settings.mdc +19 -0
  656. package/rules/rego/vscode_settings/vscode_settings.rego +30 -0
  657. package/rules/release/change.mjs +88 -0
  658. package/rules/release/docs/change.md +189 -0
  659. package/rules/release/docs/index.md +13 -0
  660. package/rules/release/docs/release.md +25 -0
  661. package/rules/release/lib/aggregate.mjs +82 -0
  662. package/rules/release/lib/change-file.mjs +116 -0
  663. package/rules/release/lib/docs/aggregate.md +250 -0
  664. package/rules/release/lib/docs/change-file.md +206 -0
  665. package/rules/release/lib/docs/fallback.md +207 -0
  666. package/rules/release/lib/docs/index.md +13 -0
  667. package/rules/release/lib/fallback.mjs +48 -0
  668. package/rules/release/main.json +1 -0
  669. package/rules/release/main.mdc +10 -0
  670. package/rules/release/release.mjs +220 -0
  671. package/rules/rust/applies/concern.json +4 -0
  672. package/rules/rust/applies/docs/index.md +11 -0
  673. package/rules/rust/applies/docs/main.md +30 -0
  674. package/rules/rust/applies/main.mjs +28 -0
  675. package/rules/rust/check/concern.json +7 -0
  676. package/rules/rust/check/docs/fix-check.md +30 -0
  677. package/rules/rust/check/docs/index.md +11 -0
  678. package/rules/rust/check/docs/main.md +37 -0
  679. package/rules/rust/check/fix-check.mjs +79 -0
  680. package/rules/rust/check/main.mjs +81 -0
  681. package/rules/rust/coverage/coverage.mdc +28 -0
  682. package/rules/rust/docs/index.md +11 -0
  683. package/rules/rust/lib/docs/has-cargo-toml.md +134 -0
  684. package/rules/rust/lib/docs/index.md +11 -0
  685. package/rules/rust/lib/has-cargo-toml.mjs +37 -0
  686. package/rules/rust/lint_rust_yml/concern.json +11 -0
  687. package/rules/rust/lint_rust_yml/lint_rust_yml.mdc +17 -0
  688. package/rules/rust/lint_rust_yml/lint_rust_yml.rego +79 -0
  689. package/rules/rust/lint_rust_yml/template/lint-rust.yml.snippet.yml +44 -0
  690. package/rules/rust/main.json +1 -0
  691. package/rules/rust/main.mdc +8 -0
  692. package/rules/rust/package_json/concern.json +10 -0
  693. package/rules/rust/package_json/package_json.mdc +12 -0
  694. package/rules/rust/package_json/package_json.rego +20 -0
  695. package/rules/rust/toolchain_cache/concern.json +5 -0
  696. package/rules/rust/toolchain_cache/docs/fix-toolchain_cache.md +35 -0
  697. package/rules/rust/toolchain_cache/docs/index.md +12 -0
  698. package/rules/rust/toolchain_cache/docs/main.md +57 -0
  699. package/rules/rust/toolchain_cache/fix-toolchain_cache.mjs +117 -0
  700. package/rules/rust/toolchain_cache/main.mjs +177 -0
  701. package/rules/rust/toolchain_cache/toolchain_cache.mdc +23 -0
  702. package/rules/rust/vscode_extensions/concern.json +11 -0
  703. package/rules/rust/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  704. package/rules/rust/vscode_extensions/docs/index.md +11 -0
  705. package/rules/rust/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  706. package/rules/rust/vscode_extensions/template/extensions.json.snippet.json +1 -0
  707. package/rules/rust/vscode_extensions/vscode_extensions.mdc +9 -0
  708. package/rules/rust/vscode_extensions/vscode_extensions.rego +15 -0
  709. package/rules/security/docs/index.md +11 -0
  710. package/rules/security/lint_security_yml/concern.json +11 -0
  711. package/rules/security/lint_security_yml/lint_security_yml.mdc +7 -0
  712. package/rules/security/lint_security_yml/lint_security_yml.rego +33 -0
  713. package/rules/security/lint_security_yml/template/lint-security.yml.snippet.yml +31 -0
  714. package/rules/security/main.json +1 -0
  715. package/rules/security/main.mdc +15 -0
  716. package/rules/security/package_json/concern.json +9 -0
  717. package/rules/security/package_json/package_json.mdc +7 -0
  718. package/rules/security/package_json/package_json.rego +19 -0
  719. package/rules/security/package_json/template/package.json.deny.json +4 -0
  720. package/rules/security/sample_secret/concern.json +11 -0
  721. package/rules/security/sample_secret/docs/index.md +11 -0
  722. package/rules/security/sample_secret/docs/main.md +29 -0
  723. package/rules/security/sample_secret/main.mjs +80 -0
  724. package/rules/security/sample_secret/sample_secret.mdc +20 -0
  725. package/rules/security/scan/concern.json +6 -0
  726. package/rules/security/scan/docs/index.md +11 -0
  727. package/rules/security/scan/docs/main.md +32 -0
  728. package/rules/security/scan/main.mjs +48 -0
  729. package/rules/security/todo.MD +27 -0
  730. package/rules/security/trufflehog/concern.json +4 -0
  731. package/rules/security/trufflehog/docs/index.md +11 -0
  732. package/rules/security/trufflehog/docs/main.md +28 -0
  733. package/rules/security/trufflehog/main.mjs +45 -0
  734. package/rules/security/trufflehog/templates/trufflehog/.trufflehog-exclude.snippet.txt +6 -0
  735. package/rules/security/trufflehog/trufflehog.mdc +21 -0
  736. package/rules/style/docs/index.md +11 -0
  737. package/rules/style/lint/concern.json +7 -0
  738. package/rules/style/lint/docs/fix-lint.md +29 -0
  739. package/rules/style/lint/docs/index.md +11 -0
  740. package/rules/style/lint/docs/main.md +29 -0
  741. package/rules/style/lint/fix-lint.mjs +66 -0
  742. package/rules/style/lint/main.mjs +68 -0
  743. package/rules/style/lint_style_yml/concern.json +9 -0
  744. package/rules/style/lint_style_yml/lint_style_yml.mdc +13 -0
  745. package/rules/style/lint_style_yml/lint_style_yml.rego +38 -0
  746. package/rules/style/lint_style_yml/template/lint-style.yml.snippet.yml +39 -0
  747. package/rules/style/main.json +1 -0
  748. package/rules/style/main.mdc +13 -0
  749. package/rules/style/package_json/concern.json +9 -0
  750. package/rules/style/package_json/package_json.mdc +18 -0
  751. package/rules/style/package_json/package_json.rego +31 -0
  752. package/rules/style/package_json/template/package.json.snippet.json +5 -0
  753. package/rules/style/tooling/concern.json +14 -0
  754. package/rules/style/tooling/docs/fix-tooling.md +29 -0
  755. package/rules/style/tooling/docs/index.md +12 -0
  756. package/rules/style/tooling/docs/main.md +34 -0
  757. package/rules/style/tooling/fix-tooling.mjs +58 -0
  758. package/rules/style/tooling/main.mjs +78 -0
  759. package/rules/style/tooling/tooling.mdc +85 -0
  760. package/rules/style/vscode_extensions/concern.json +9 -0
  761. package/rules/style/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  762. package/rules/style/vscode_extensions/docs/index.md +11 -0
  763. package/rules/style/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  764. package/rules/style/vscode_extensions/template/extensions.json.snippet.json +1 -0
  765. package/rules/style/vscode_extensions/vscode_extensions.mdc +13 -0
  766. package/rules/style/vscode_extensions/vscode_extensions.rego +13 -0
  767. package/rules/style/vscode_settings/concern.json +9 -0
  768. package/rules/style/vscode_settings/template/settings.json.snippet.json +5 -0
  769. package/rules/style/vscode_settings/vscode_settings.mdc +19 -0
  770. package/rules/style/vscode_settings/vscode_settings.rego +15 -0
  771. package/rules/tauri/cargo_mutants_config/cargo_mutants_config.mdc +39 -0
  772. package/rules/tauri/cargo_mutants_config/concern.json +5 -0
  773. package/rules/tauri/cargo_mutants_config/docs/fix-cargo_mutants_config.md +30 -0
  774. package/rules/tauri/cargo_mutants_config/docs/index.md +12 -0
  775. package/rules/tauri/cargo_mutants_config/docs/main.md +30 -0
  776. package/rules/tauri/cargo_mutants_config/fix-cargo_mutants_config.mjs +53 -0
  777. package/rules/tauri/cargo_mutants_config/main.mjs +148 -0
  778. package/rules/tauri/core_test_isolation/concern.json +5 -0
  779. package/rules/tauri/core_test_isolation/core_test_isolation.mdc +43 -0
  780. package/rules/tauri/core_test_isolation/docs/index.md +9 -0
  781. package/rules/tauri/core_test_isolation/docs/main.md +36 -0
  782. package/rules/tauri/core_test_isolation/main.mjs +166 -0
  783. package/rules/tauri/docs/index.md +11 -0
  784. package/rules/tauri/linux_deps/concern.json +8 -0
  785. package/rules/tauri/linux_deps/docs/fix-linux_deps.md +29 -0
  786. package/rules/tauri/linux_deps/docs/index.md +10 -0
  787. package/rules/tauri/linux_deps/docs/main.md +36 -0
  788. package/rules/tauri/linux_deps/fix-linux_deps.mjs +89 -0
  789. package/rules/tauri/linux_deps/linux_deps.mdc +18 -0
  790. package/rules/tauri/linux_deps/main.mjs +100 -0
  791. package/rules/tauri/main.json +1 -0
  792. package/rules/tauri/main.mdc +86 -0
  793. package/rules/tauri/release/concern.json +8 -0
  794. package/rules/tauri/release/docs/fix-release.md +28 -0
  795. package/rules/tauri/release/docs/index.md +10 -0
  796. package/rules/tauri/release/docs/main.md +32 -0
  797. package/rules/tauri/release/fix-release.mjs +353 -0
  798. package/rules/tauri/release/main.mjs +315 -0
  799. package/rules/tauri/release/release.mdc +104 -0
  800. package/rules/tauri/tooling/concern.json +8 -0
  801. package/rules/tauri/tooling/docs/index.md +11 -0
  802. package/rules/tauri/tooling/docs/main.md +34 -0
  803. package/rules/tauri/tooling/main.mjs +94 -0
  804. package/rules/tauri/tooling/tooling.mdc +27 -0
  805. package/rules/tauri/updater/concern.json +14 -0
  806. package/rules/tauri/updater/docs/fix-updater.md +33 -0
  807. package/rules/tauri/updater/docs/index.md +10 -0
  808. package/rules/tauri/updater/docs/main.md +32 -0
  809. package/rules/tauri/updater/fix-updater.mjs +322 -0
  810. package/rules/tauri/updater/main.mjs +403 -0
  811. package/rules/tauri/updater/updater.mdc +90 -0
  812. package/rules/tauri/vscode_extensions/concern.json +9 -0
  813. package/rules/tauri/vscode_extensions/docs/fix-vscode_extensions.md +25 -0
  814. package/rules/tauri/vscode_extensions/docs/index.md +11 -0
  815. package/rules/tauri/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  816. package/rules/tauri/vscode_extensions/vscode_extensions.mdc +23 -0
  817. package/rules/tauri/vscode_extensions/vscode_extensions.rego +26 -0
  818. package/rules/test/cargo_mutants_config/cargo_mutants_config.mdc +18 -0
  819. package/rules/test/cargo_mutants_config/concern.json +8 -0
  820. package/rules/test/cargo_mutants_config/data/cargo_mutants_config/mutants.toml.baseline +7 -0
  821. package/rules/test/cargo_mutants_config/docs/fix-cargo_mutants_config.md +31 -0
  822. package/rules/test/cargo_mutants_config/docs/index.md +12 -0
  823. package/rules/test/cargo_mutants_config/docs/main.md +36 -0
  824. package/rules/test/cargo_mutants_config/fix-cargo_mutants_config.mjs +49 -0
  825. package/rules/test/cargo_mutants_config/main.mjs +62 -0
  826. package/rules/test/docs/index.md +11 -0
  827. package/rules/test/location/concern.json +8 -0
  828. package/rules/test/location/docs/index.md +11 -0
  829. package/rules/test/location/docs/main.md +36 -0
  830. package/rules/test/location/location.mdc +52 -0
  831. package/rules/test/location/main.mjs +70 -0
  832. package/rules/test/main.json +1 -0
  833. package/rules/test/main.mdc +26 -0
  834. package/rules/test/no-bun-test-import/concern.json +7 -0
  835. package/rules/test/no-bun-test-import/docs/fix-no-bun-test-import.md +31 -0
  836. package/rules/test/no-bun-test-import/docs/index.md +10 -0
  837. package/rules/test/no-bun-test-import/docs/main.md +36 -0
  838. package/rules/test/no-bun-test-import/fix-no-bun-test-import.mjs +51 -0
  839. package/rules/test/no-bun-test-import/main.mjs +105 -0
  840. package/rules/test/no-bun-test-import/no-bun-test-import.mdc +9 -0
  841. package/rules/test/no-console-store-restore/concern.json +7 -0
  842. package/rules/test/no-console-store-restore/docs/index.md +11 -0
  843. package/rules/test/no-console-store-restore/docs/main.md +44 -0
  844. package/rules/test/no-console-store-restore/main.mjs +88 -0
  845. package/rules/test/no-console-store-restore/no-console-store-restore.mdc +11 -0
  846. package/rules/test/no-process-chdir/concern.json +7 -0
  847. package/rules/test/no-process-chdir/docs/index.md +11 -0
  848. package/rules/test/no-process-chdir/docs/main.md +32 -0
  849. package/rules/test/no-process-chdir/main.mjs +40 -0
  850. package/rules/test/no-process-chdir/no-process-chdir.mdc +15 -0
  851. package/rules/test/no-relative-fs-path/concern.json +7 -0
  852. package/rules/test/no-relative-fs-path/docs/index.md +11 -0
  853. package/rules/test/no-relative-fs-path/docs/main.md +34 -0
  854. package/rules/test/no-relative-fs-path/main.mjs +239 -0
  855. package/rules/test/no-relative-fs-path/no-relative-fs-path.mdc +22 -0
  856. package/rules/test/package_json/concern.json +11 -0
  857. package/rules/test/package_json/package_json.mdc +18 -0
  858. package/rules/test/package_json/package_json.rego +25 -0
  859. package/rules/test/package_json/template/package.json.contains.json +6 -0
  860. package/rules/test/sandbox-aware-test/concern.json +7 -0
  861. package/rules/test/sandbox-aware-test/docs/index.md +11 -0
  862. package/rules/test/sandbox-aware-test/docs/main.md +55 -0
  863. package/rules/test/sandbox-aware-test/main.mjs +89 -0
  864. package/rules/test/sandbox-aware-test/sandbox-aware-test.mdc +28 -0
  865. package/rules/test/stryker_config/concern.json +8 -0
  866. package/rules/test/stryker_config/data/stryker_config/docs/index.md +13 -0
  867. package/rules/test/stryker_config/data/stryker_config/docs/stryker-vue-macros-ignorer.md +31 -0
  868. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.baseline.md +31 -0
  869. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.vue.baseline.md +35 -0
  870. package/rules/test/stryker_config/data/stryker_config/stryker-vue-macros-ignorer.mjs +48 -0
  871. package/rules/test/stryker_config/data/stryker_config/stryker.config.baseline.mjs +18 -0
  872. package/rules/test/stryker_config/data/stryker_config/stryker.config.vue.baseline.mjs +23 -0
  873. package/rules/test/stryker_config/data/vitest_config/docs/index.md +11 -0
  874. package/rules/test/stryker_config/data/vitest_config/docs/vitest.config.baseline.md +35 -0
  875. package/rules/test/stryker_config/data/vitest_config/vitest.config.baseline.js +22 -0
  876. package/rules/test/stryker_config/docs/fix-stryker_config.md +42 -0
  877. package/rules/test/stryker_config/docs/index.md +12 -0
  878. package/rules/test/stryker_config/docs/main.md +38 -0
  879. package/rules/test/stryker_config/fix-stryker_config.mjs +76 -0
  880. package/rules/test/stryker_config/main.mjs +504 -0
  881. package/rules/test/stryker_config/stryker_config.mdc +26 -0
  882. package/rules/test/vitest-config-pool-forks/concern.json +7 -0
  883. package/rules/test/vitest-config-pool-forks/docs/index.md +11 -0
  884. package/rules/test/vitest-config-pool-forks/docs/main.md +42 -0
  885. package/rules/test/vitest-config-pool-forks/main.mjs +41 -0
  886. package/rules/test/vitest-config-pool-forks/vitest-config-pool-forks.mdc +34 -0
  887. package/rules/text/cspell/concern.json +9 -0
  888. package/rules/text/cspell/cspell.mdc +41 -0
  889. package/rules/text/cspell/cspell.rego +71 -0
  890. package/rules/text/cspell/docs/fix-cspell.md +36 -0
  891. package/rules/text/cspell/docs/index.md +11 -0
  892. package/rules/text/cspell/fix-cspell.mjs +115 -0
  893. package/rules/text/cspell/template/.cspell.json.contains.json +3 -0
  894. package/rules/text/cspell/template/.cspell.json.deny.json +5 -0
  895. package/rules/text/cspell/template/.cspell.json.snippet.json +15 -0
  896. package/rules/text/cspell-fix/concern.json +7 -0
  897. package/rules/text/cspell-fix/docs/fix-worker.md +38 -0
  898. package/rules/text/cspell-fix/docs/index.md +12 -0
  899. package/rules/text/cspell-fix/docs/main.md +32 -0
  900. package/rules/text/cspell-fix/fix-worker.mjs +73 -0
  901. package/rules/text/cspell-fix/main.mjs +185 -0
  902. package/rules/text/docs/index.md +11 -0
  903. package/rules/text/forbidden-prettier/concern.json +7 -0
  904. package/rules/text/forbidden-prettier/docs/index.md +11 -0
  905. package/rules/text/forbidden-prettier/docs/main.md +38 -0
  906. package/rules/text/forbidden-prettier/forbidden-prettier.mdc +14 -0
  907. package/rules/text/forbidden-prettier/main.mjs +56 -0
  908. package/rules/text/formatting/concern.json +17 -0
  909. package/rules/text/formatting/docs/index.md +11 -0
  910. package/rules/text/formatting/docs/main.md +39 -0
  911. package/rules/text/formatting/main.mjs +149 -0
  912. package/rules/text/lint_text/concern.json +8 -0
  913. package/rules/text/lint_text/lint_text.mdc +19 -0
  914. package/rules/text/lint_text/lint_text.rego +104 -0
  915. package/rules/text/lint_text/template/lint-text.yml.snippet.yml +61 -0
  916. package/rules/text/main.json +1 -0
  917. package/rules/text/main.mdc +23 -0
  918. package/rules/text/markdownlint/concern.json +12 -0
  919. package/rules/text/markdownlint/docs/fix-markdownlint.md +38 -0
  920. package/rules/text/markdownlint/docs/index.md +12 -0
  921. package/rules/text/markdownlint/docs/main.md +40 -0
  922. package/rules/text/markdownlint/fix-markdownlint.mjs +64 -0
  923. package/rules/text/markdownlint/main.mjs +55 -0
  924. package/rules/text/markdownlint/markdownlint.mdc +40 -0
  925. package/rules/text/markdownlint/markdownlint.rego +57 -0
  926. package/rules/text/markdownlint/template/.markdownlint-cli2.jsonc.snippet.jsonc +11 -0
  927. package/rules/text/oxfmt/concern.json +7 -0
  928. package/rules/text/oxfmt/docs/fix-oxfmt.md +28 -0
  929. package/rules/text/oxfmt/docs/main.md +27 -0
  930. package/rules/text/oxfmt/fix-oxfmt.mjs +52 -0
  931. package/rules/text/oxfmt/main.mjs +48 -0
  932. package/rules/text/oxfmt/oxfmt.mdc +11 -0
  933. package/rules/text/oxfmtrc/concern.json +9 -0
  934. package/rules/text/oxfmtrc/oxfmtrc.mdc +11 -0
  935. package/rules/text/oxfmtrc/oxfmtrc.rego +55 -0
  936. package/rules/text/oxfmtrc/template/.oxfmtrc.json.snippet.json +8 -0
  937. package/rules/text/package_json/concern.json +9 -0
  938. package/rules/text/package_json/package_json.mdc +35 -0
  939. package/rules/text/package_json/package_json.rego +66 -0
  940. package/rules/text/package_json/template/package.json.deny.json +15 -0
  941. package/rules/text/run-dotenv-linter/concern.json +7 -0
  942. package/rules/text/run-dotenv-linter/docs/fix-run-dotenv-linter.md +43 -0
  943. package/rules/text/run-dotenv-linter/docs/index.md +12 -0
  944. package/rules/text/run-dotenv-linter/docs/main.md +35 -0
  945. package/rules/text/run-dotenv-linter/fix-run-dotenv-linter.mjs +64 -0
  946. package/rules/text/run-dotenv-linter/main.mjs +122 -0
  947. package/rules/text/run-shellcheck/concern.json +7 -0
  948. package/rules/text/run-shellcheck/docs/fix-run-shellcheck.md +40 -0
  949. package/rules/text/run-shellcheck/docs/index.md +12 -0
  950. package/rules/text/run-shellcheck/docs/main.md +31 -0
  951. package/rules/text/run-shellcheck/fix-run-shellcheck.mjs +44 -0
  952. package/rules/text/run-shellcheck/main.mjs +245 -0
  953. package/rules/text/run-v8r/concern.json +7 -0
  954. package/rules/text/run-v8r/docs/index.md +11 -0
  955. package/rules/text/run-v8r/docs/main.md +40 -0
  956. package/rules/text/run-v8r/main.mjs +266 -0
  957. package/rules/text/vscode_extensions/concern.json +9 -0
  958. package/rules/text/vscode_extensions/docs/fix-vscode_extensions.md +36 -0
  959. package/rules/text/vscode_extensions/docs/index.md +11 -0
  960. package/rules/text/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  961. package/rules/text/vscode_extensions/template/extensions.json.snippet.json +3 -0
  962. package/rules/text/vscode_extensions/vscode_extensions.mdc +13 -0
  963. package/rules/text/vscode_extensions/vscode_extensions.rego +12 -0
  964. package/rules/text/vscode_settings/concern.json +9 -0
  965. package/rules/text/vscode_settings/template/settings.json.snippet.json +9 -0
  966. package/rules/text/vscode_settings/vscode_settings.mdc +13 -0
  967. package/rules/text/vscode_settings/vscode_settings.rego +34 -0
  968. package/rules/tool-surface/docs/index.md +11 -0
  969. package/rules/tool-surface/main.json +6 -0
  970. package/rules/tool-surface/main.mdc +72 -0
  971. package/rules/vue/docs/index.md +11 -0
  972. package/rules/vue/lib/docs/index.md +11 -0
  973. package/rules/vue/lib/docs/vue-forbidden-imports.md +265 -0
  974. package/rules/vue/lib/vue-forbidden-imports.mjs +264 -0
  975. package/rules/vue/main.json +1 -0
  976. package/rules/vue/main.mdc +18 -0
  977. package/rules/vue/package_json/concern.json +9 -0
  978. package/rules/vue/package_json/package_json.mdc +30 -0
  979. package/rules/vue/package_json/package_json.rego +140 -0
  980. package/rules/vue/packages/concern.json +6 -0
  981. package/rules/vue/packages/docs/index.md +11 -0
  982. package/rules/vue/packages/docs/main.md +35 -0
  983. package/rules/vue/packages/main.mjs +575 -0
  984. package/rules/worktree/docs/index.md +11 -0
  985. package/rules/worktree/main.json +1 -0
  986. package/rules/worktree/main.mdc +100 -0
  987. package/rules/worktree/vscode_settings/concern.json +10 -0
  988. package/rules/worktree/vscode_settings/template/settings.json.snippet.json +8 -0
  989. package/rules/worktree/zed_settings/concern.json +10 -0
  990. package/rules/worktree/zed_settings/template/settings.json.snippet.json +12 -0
  991. package/schemas/any.json +4 -0
  992. package/schemas/concern.json +108 -0
  993. package/schemas/layers-config.json +38 -0
  994. package/schemas/n-rules.json +65 -0
  995. package/schemas/rule-meta.json +39 -0
  996. package/schemas/skill-meta.json +30 -0
  997. package/schemas/target.json +63 -0
  998. package/schemas/v8r-catalog.json +179 -0
  999. package/schemas/vendor/bunfig.json +616 -0
  1000. package/schemas/vendor/cargo-mutants-config.json +158 -0
  1001. package/schemas/vendor/cargo.json +9438 -0
  1002. package/schemas/vendor/claude-code-settings.json +2742 -0
  1003. package/schemas/vendor/codex-hooks.json +148 -0
  1004. package/schemas/vendor/cspell.json +2427 -0
  1005. package/schemas/vendor/github-action.json +695 -0
  1006. package/schemas/vendor/github-workflow.json +2193 -0
  1007. package/schemas/vendor/jsconfig.json +1252 -0
  1008. package/schemas/vendor/jscpd.json +405 -0
  1009. package/schemas/vendor/knip.json +915 -0
  1010. package/schemas/vendor/mcp.json +26 -0
  1011. package/schemas/vendor/mt-config.json +85 -0
  1012. package/schemas/vendor/oxfmtrc.json +810 -0
  1013. package/schemas/vendor/oxlintrc.json +18690 -0
  1014. package/schemas/vendor/package.json +23798 -0
  1015. package/schemas/vendor/prettierrc.json +433 -0
  1016. package/schemas/vendor/quikrun.json +195 -0
  1017. package/schemas/vendor/schema-catalog.json +62 -0
  1018. package/schemas/vendor/tsconfig.json +1535 -0
  1019. package/schemas/vendor/zizmor.json +489 -0
  1020. package/scripts/auto-rules.mjs +444 -0
  1021. package/scripts/auto-skills.mjs +95 -0
  1022. package/scripts/build-agents-commands.mjs +91 -0
  1023. package/scripts/cli-entry.mjs +34 -0
  1024. package/scripts/dispatcher/docs/index.md +11 -0
  1025. package/scripts/docs/auto-rules.md +34 -0
  1026. package/scripts/docs/auto-skills.md +30 -0
  1027. package/scripts/docs/build-agents-commands.md +37 -0
  1028. package/scripts/docs/cli-entry.md +36 -0
  1029. package/scripts/docs/ensure-n-rules-dev-dependencies.md +40 -0
  1030. package/scripts/docs/hook.md +30 -0
  1031. package/scripts/docs/index.md +22 -0
  1032. package/scripts/docs/post-tool-use-check.md +27 -0
  1033. package/scripts/docs/rename-yaml-extensions.md +40 -0
  1034. package/scripts/docs/skills-cli.md +35 -0
  1035. package/scripts/docs/smoke-check-imports.md +31 -0
  1036. package/scripts/docs/sync-claude-config.md +84 -0
  1037. package/scripts/docs/sync-setup-bun-deps-action.md +28 -0
  1038. package/scripts/docs/update-blue-oak.md +28 -0
  1039. package/scripts/docs/upgrade-n-rules-and-install.md +36 -0
  1040. package/scripts/ensure-n-rules-dev-dependencies.mjs +217 -0
  1041. package/scripts/hook.mjs +100 -0
  1042. package/scripts/lib/adr/docs/index.md +12 -0
  1043. package/scripts/lib/adr/docs/normalize-cli.md +36 -0
  1044. package/scripts/lib/adr/docs/normalize-pipeline.md +45 -0
  1045. package/scripts/lib/adr/normalize-cli.mjs +74 -0
  1046. package/scripts/lib/adr/normalize-pipeline.mjs +701 -0
  1047. package/scripts/lib/assert-project-root.mjs +77 -0
  1048. package/scripts/lib/blue-oak.mjs +41 -0
  1049. package/scripts/lib/changed-files.mjs +83 -0
  1050. package/scripts/lib/check-reporter.mjs +27 -0
  1051. package/scripts/lib/collect-test-files.mjs +48 -0
  1052. package/scripts/lib/concern-meta.mjs +140 -0
  1053. package/scripts/lib/diff-added-lines.mjs +86 -0
  1054. package/scripts/lib/discover-check-rules-from-cursor.mjs +40 -0
  1055. package/scripts/lib/discover-checkable-rules.mjs +49 -0
  1056. package/scripts/lib/docs/assert-project-root.md +30 -0
  1057. package/scripts/lib/docs/blue-oak.md +29 -0
  1058. package/scripts/lib/docs/changed-files.md +32 -0
  1059. package/scripts/lib/docs/check-reporter.md +179 -0
  1060. package/scripts/lib/docs/collect-test-files.md +32 -0
  1061. package/scripts/lib/docs/concern-meta.md +34 -0
  1062. package/scripts/lib/docs/diff-added-lines.md +38 -0
  1063. package/scripts/lib/docs/discover-check-rules-from-cursor.md +29 -0
  1064. package/scripts/lib/docs/discover-checkable-rules.md +25 -0
  1065. package/scripts/lib/docs/ensure-tool.md +258 -0
  1066. package/scripts/lib/docs/generated-markdown.md +279 -0
  1067. package/scripts/lib/docs/gha-workflow.md +38 -0
  1068. package/scripts/lib/docs/index.md +40 -0
  1069. package/scripts/lib/docs/inline-template-links.md +25 -0
  1070. package/scripts/lib/docs/list-project-rules-mdc.md +27 -0
  1071. package/scripts/lib/docs/list-rule-ids.md +25 -0
  1072. package/scripts/lib/docs/load-cursor-config.md +154 -0
  1073. package/scripts/lib/docs/mirror-parity.md +32 -0
  1074. package/scripts/lib/docs/read-n-rules-config-lite.md +26 -0
  1075. package/scripts/lib/docs/resolve-target-files.md +38 -0
  1076. package/scripts/lib/docs/root-notice.md +29 -0
  1077. package/scripts/lib/docs/rule-meta-helpers.md +38 -0
  1078. package/scripts/lib/docs/rule-meta.md +29 -0
  1079. package/scripts/lib/docs/rule-predicates.md +31 -0
  1080. package/scripts/lib/docs/run-conftest-batch.md +30 -0
  1081. package/scripts/lib/docs/run-lint-step.md +29 -0
  1082. package/scripts/lib/docs/run-standard-lint.md +43 -0
  1083. package/scripts/lib/docs/skill-meta.md +62 -0
  1084. package/scripts/lib/docs/sync-gitignore-worktree.md +26 -0
  1085. package/scripts/lib/docs/template.md +44 -0
  1086. package/scripts/lib/docs/timing-summary.md +25 -0
  1087. package/scripts/lib/docs/workspaces.md +34 -0
  1088. package/scripts/lib/docs/worktree-notice.md +27 -0
  1089. package/scripts/lib/ensure-tool.mjs +352 -0
  1090. package/scripts/lib/fix/docs/index.md +11 -0
  1091. package/scripts/lib/fix/docs/vscode-ext-add.md +33 -0
  1092. package/scripts/lib/fix/vscode-ext-add.mjs +53 -0
  1093. package/scripts/lib/generated-markdown.mjs +71 -0
  1094. package/scripts/lib/gha-workflow.mjs +220 -0
  1095. package/scripts/lib/inline-template-links.mjs +108 -0
  1096. package/scripts/lib/lint-surface/codegen-opa-wrapper.mjs +30 -0
  1097. package/scripts/lib/lint-surface/collateral-veto.mjs +55 -0
  1098. package/scripts/lib/lint-surface/default-worker.mjs +67 -0
  1099. package/scripts/lib/lint-surface/detect.mjs +169 -0
  1100. package/scripts/lib/lint-surface/docs/codegen-opa-wrapper.md +30 -0
  1101. package/scripts/lib/lint-surface/docs/collateral-veto.md +28 -0
  1102. package/scripts/lib/lint-surface/docs/default-worker.md +32 -0
  1103. package/scripts/lib/lint-surface/docs/detect.md +38 -0
  1104. package/scripts/lib/lint-surface/docs/index.md +27 -0
  1105. package/scripts/lib/lint-surface/docs/ladder.md +33 -0
  1106. package/scripts/lib/lint-surface/docs/lint-lock.md +47 -0
  1107. package/scripts/lib/lint-surface/docs/mt-run-node.md +37 -0
  1108. package/scripts/lib/lint-surface/docs/mt-tail.md +41 -0
  1109. package/scripts/lib/lint-surface/docs/policy-lint-adapter.md +44 -0
  1110. package/scripts/lib/lint-surface/docs/policy-test-step.md +43 -0
  1111. package/scripts/lib/lint-surface/docs/progress.md +28 -0
  1112. package/scripts/lib/lint-surface/docs/render.md +29 -0
  1113. package/scripts/lib/lint-surface/docs/run-detectors.md +32 -0
  1114. package/scripts/lib/lint-surface/docs/run-fix.md +33 -0
  1115. package/scripts/lib/lint-surface/docs/snapshot.md +30 -0
  1116. package/scripts/lib/lint-surface/docs/tier-sampling-bench.md +40 -0
  1117. package/scripts/lib/lint-surface/docs/tier-sampling-experiment.md +35 -0
  1118. package/scripts/lib/lint-surface/docs/types.md +27 -0
  1119. package/scripts/lib/lint-surface/docs/violation-reporter.md +32 -0
  1120. package/scripts/lib/lint-surface/ladder.mjs +92 -0
  1121. package/scripts/lib/lint-surface/lint-lock.mjs +247 -0
  1122. package/scripts/lib/lint-surface/mt-run-node.mjs +206 -0
  1123. package/scripts/lib/lint-surface/mt-tail.mjs +0 -0
  1124. package/scripts/lib/lint-surface/policy-lint-adapter.mjs +101 -0
  1125. package/scripts/lib/lint-surface/policy-test-step.mjs +149 -0
  1126. package/scripts/lib/lint-surface/progress.mjs +198 -0
  1127. package/scripts/lib/lint-surface/render.mjs +50 -0
  1128. package/scripts/lib/lint-surface/run-detectors.mjs +314 -0
  1129. package/scripts/lib/lint-surface/run-fix.mjs +732 -0
  1130. package/scripts/lib/lint-surface/snapshot.mjs +83 -0
  1131. package/scripts/lib/lint-surface/tier-sampling-bench.mjs +457 -0
  1132. package/scripts/lib/lint-surface/tier-sampling-experiment.mjs +289 -0
  1133. package/scripts/lib/lint-surface/types.mjs +150 -0
  1134. package/scripts/lib/lint-surface/violation-reporter.mjs +46 -0
  1135. package/scripts/lib/list-project-rules-mdc.mjs +22 -0
  1136. package/scripts/lib/list-rule-ids.mjs +32 -0
  1137. package/scripts/lib/load-cursor-config.mjs +58 -0
  1138. package/scripts/lib/mirror-parity.mjs +62 -0
  1139. package/scripts/lib/read-n-rules-config-lite.mjs +63 -0
  1140. package/scripts/lib/resolve-target-files.mjs +103 -0
  1141. package/scripts/lib/root-notice.mjs +67 -0
  1142. package/scripts/lib/rule-meta-helpers.mjs +103 -0
  1143. package/scripts/lib/rule-meta.mjs +66 -0
  1144. package/scripts/lib/rule-predicates.mjs +114 -0
  1145. package/scripts/lib/run-conftest-batch.mjs +124 -0
  1146. package/scripts/lib/run-lint-step.mjs +38 -0
  1147. package/scripts/lib/run-standard-lint.mjs +50 -0
  1148. package/scripts/lib/skill-meta.mjs +90 -0
  1149. package/scripts/lib/sync-gitignore-worktree.mjs +27 -0
  1150. package/scripts/lib/template.mjs +315 -0
  1151. package/scripts/lib/timing-summary.mjs +63 -0
  1152. package/scripts/lib/workspaces.mjs +109 -0
  1153. package/scripts/lib/worktree-notice.mjs +183 -0
  1154. package/scripts/post-tool-use-check.mjs +82 -0
  1155. package/scripts/rename-yaml-extensions.mjs +170 -0
  1156. package/scripts/skills-cli.mjs +262 -0
  1157. package/scripts/smoke-check-imports.mjs +66 -0
  1158. package/scripts/sync-claude-config.mjs +692 -0
  1159. package/scripts/sync-setup-bun-deps-action.mjs +36 -0
  1160. package/scripts/update-blue-oak.mjs +50 -0
  1161. package/scripts/upgrade-n-rules-and-install.mjs +264 -0
  1162. package/scripts/utils/apply-to-files.mjs +36 -0
  1163. package/scripts/utils/ast-extract.mjs +149 -0
  1164. package/scripts/utils/ast-scan-utils.mjs +206 -0
  1165. package/scripts/utils/docs/apply-to-files.md +38 -0
  1166. package/scripts/utils/docs/ast-extract.md +30 -0
  1167. package/scripts/utils/docs/ast-scan-utils.md +54 -0
  1168. package/scripts/utils/docs/ensure-gitignore-entries.md +32 -0
  1169. package/scripts/utils/docs/find-package-json-paths.md +30 -0
  1170. package/scripts/utils/docs/index.md +23 -0
  1171. package/scripts/utils/docs/lock-cache-dir.md +29 -0
  1172. package/scripts/utils/docs/pass.md +29 -0
  1173. package/scripts/utils/docs/resolve-cargo-manifest.md +27 -0
  1174. package/scripts/utils/docs/resolve-cmd.md +33 -0
  1175. package/scripts/utils/docs/resolve-js-root.md +26 -0
  1176. package/scripts/utils/docs/test-helpers.md +30 -0
  1177. package/scripts/utils/docs/walk-cache.md +31 -0
  1178. package/scripts/utils/docs/walkDir.md +31 -0
  1179. package/scripts/utils/docs/with-lock.md +30 -0
  1180. package/scripts/utils/docs/worktree-fingerprint.md +31 -0
  1181. package/scripts/utils/ensure-gitignore-entries.mjs +30 -0
  1182. package/scripts/utils/find-package-json-paths.mjs +30 -0
  1183. package/scripts/utils/lock-cache-dir.mjs +37 -0
  1184. package/scripts/utils/pass.mjs +9 -0
  1185. package/scripts/utils/resolve-cargo-manifest.mjs +62 -0
  1186. package/scripts/utils/resolve-cmd.mjs +25 -0
  1187. package/scripts/utils/resolve-js-root.mjs +61 -0
  1188. package/scripts/utils/walk-cache.mjs +24 -0
  1189. package/scripts/utils/walkDir.mjs +55 -0
  1190. package/scripts/utils/with-lock.mjs +190 -0
  1191. package/scripts/utils/worktree-fingerprint.mjs +33 -0
  1192. package/skills/adr-normalize/SKILL.md +73 -0
  1193. package/skills/adr-normalize/main.json +1 -0
  1194. package/skills/brainstorming/SKILL.md +165 -0
  1195. package/skills/brainstorming/main.json +1 -0
  1196. package/skills/doc-aggregate/SKILL.md +121 -0
  1197. package/skills/doc-aggregate/js/docs/index.md +11 -0
  1198. package/skills/doc-aggregate/main.json +1 -0
  1199. package/skills/doc-files/.changes/260612-0002.md +6 -0
  1200. package/skills/doc-files/.changes/260612-0006.md +6 -0
  1201. package/skills/doc-files/.changes/260612-0008.md +6 -0
  1202. package/skills/doc-files/.changes/260612-0012.md +6 -0
  1203. package/skills/doc-files/.changes/260612-0031.md +6 -0
  1204. package/skills/doc-files/.changes/260612-0036.md +6 -0
  1205. package/skills/doc-files/.changes/260612-0114.md +6 -0
  1206. package/skills/doc-files/SKILL.md +86 -0
  1207. package/skills/doc-files/main.json +1 -0
  1208. package/skills/lint/SKILL.md +121 -0
  1209. package/skills/lint/main.json +1 -0
  1210. package/skills/llm-patch/SKILL.md +260 -0
  1211. package/skills/llm-patch/main.json +1 -0
  1212. package/skills/publish-telegram/SKILL.md +93 -0
  1213. package/skills/publish-telegram/main.json +1 -0
  1214. package/skills/taze/SKILL.md +114 -0
  1215. package/skills/taze/js/diff.mjs +140 -0
  1216. package/skills/taze/js/docs/diff.md +55 -0
  1217. package/skills/taze/js/docs/index.md +11 -0
  1218. package/skills/taze/main.json +1 -0
  1219. package/types/bin/n-rules.d.ts +2 -0
@@ -0,0 +1,701 @@
1
+ /**
2
+ * ADR normalize — локально-орієнтований конвеєр (інверсія керування: JS оркеструє,
3
+ * LLM відповідає лише на вузькі verifiable-питання). Альтернатива single-shot-у
4
+ * normalize-decisions.sh, заточена під малу локальну модель (omlx/gemma-4b).
5
+ *
6
+ * Принцип: модель НІКОЛИ не приймає глобальних рішень, не повертає великих
7
+ * структур і НЕ форматує. Глобальний стан (кластери, слаги, покриття) та весь
8
+ * MADR-каркас (заголовок, Status/Date, назви секцій, fallback-фрази, шаблон
9
+ * "Chosen option…") тримає JS. Модель повертає лише вузький, verifiable зміст:
10
+ * - судить пару записів бінарно «те саме рішення? так/ні» (Stage 1),
11
+ * - для ізольованого драфта каже standalone/trivial (Stage 1b),
12
+ * - витягує зміст секцій одного драфта як JSON (Stage 2) — каркас будує JS,
13
+ * - пише short merge-additions без заголовка (Stage 3) — «## Update <date>» додає JS.
14
+ *
15
+ * Стадії:
16
+ * 0. retrieval (JS) — лексична схожість → кандидати-ребра draft↔draft / draft↔clean
17
+ * 1. edge-judge (LLM) — бінарне same/different по кожному ребру (self-consistency)
18
+ * 1b. kind-judge(LLM) — standalone vs trivial для драфтів без ребер
19
+ * ── cluster (JS) — union-find по підтверджених ребрах, вибір anchor, призначення op
20
+ * 2. gen-MADR — LLM витягує секції-JSON → assembleMadr() (JS) збирає канон → validation gate
21
+ * 3. gen-merge — LLM пише additions-прозу → JS додає «## Update <date>»-заголовок
22
+ * ── assemble (JS) — operations[] у форматі, сумісному з apply-ops
23
+ *
24
+ * Повертає той самий operations[]-контракт, що й single-shot — apply-логіка спільна.
25
+ */
26
+ import { z } from 'zod'
27
+ import { runOneShot } from '@7n/llm-lib/one-shot'
28
+ import { startChain } from '@7n/llm-lib/chain'
29
+ import { CLOUD_MIN, resolveModel } from '@7n/llm-lib/model-tiers'
30
+
31
+ // ─────────────────────────── Stage 0: retrieval (JS) ───────────────────────────
32
+
33
+ const STOP = new Set(['adr', 'та', 'для', 'через', 'на', 'в', 'у', 'з', 'із', 'до', 'і', 'й', 'the', 'a', 'of', 'md'])
34
+
35
+ // Module-scope regex (oxlint prefer-static-regex: без рекомпіляції на кожен виклик).
36
+ const RE_MD_EXT = /\.md$/
37
+ const RE_TS_PREFIX = /^\d{6,8}-\d{4,6}-/
38
+ const RE_FENCE_OPEN = /^\s*```[a-z]*\s*\n?/i
39
+ const RE_FENCE_CLOSE = /\n?```\s*$/i
40
+ const RE_SLUG_NONWORD = /[^a-zа-яіїєґ0-9]+/gi
41
+ const RE_LEAD_HYPHEN = /^-+/
42
+ const RE_TRAIL_HYPHEN = /-+$/
43
+ const RE_UPDATE_HEAD = /^##\s+Update/
44
+ const RE_UPDATE_HEAD_LINE = /^##\s+Update[^\n]*\n+/
45
+ const RE_DECISION_SECTION = /##\s*Decision Outcome\s*([\s\S]{0,500})/i
46
+ const RE_NO_DECISION = /(не\s+обрано|не\s+прийнят|рішення\s+не\s+прийн|не\s+зроблен|no\s+decision|undecided)/i
47
+ const RE_FENCE_LEAD = /^\s*```/
48
+ const RE_FENCE_TRAIL = /```\s*$/
49
+ const RE_SESSION = /\bsession:\s/
50
+ const RE_STATUS = /\*\*Status:\*\*/
51
+ const RE_DATE = /\*\*Date:\*\*\s*\d{4}-\d{2}-\d{2}/
52
+ const RE_TOKEN_SPLIT = /[^a-zа-яіїєґ0-9]+/i
53
+ const RE_DRAFT_ADR_TITLE = /^#{1,2}\s+ADR\s+(.+)$/m
54
+ const RE_INFRA_ERROR = /registry:|session:|не знайдена/i
55
+ const RE_YAML_FRONTMATTER = /^---\n([\s\S]*?)\n---/
56
+ const RE_TYPE_ADR = /^type:\s*ADR\s*$/m
57
+
58
+ /**
59
+ * Прибирає code-fence-обгортку з LLM-відповіді.
60
+ * @param {string} raw сира відповідь LLM
61
+ * @returns {string} текст без обгортки code-fence
62
+ */
63
+ const stripFence = (raw) => raw.replace(RE_FENCE_OPEN, '').replace(RE_FENCE_CLOSE, '').trim()
64
+ /**
65
+ * Назва clean-ADR → людський заголовок (без .md і timestamp-префікса).
66
+ * @param {string} s basename clean-ADR
67
+ * @returns {string} людський заголовок
68
+ */
69
+ const stripAdrName = (s) => s.replace(RE_MD_EXT, '').replace(RE_TS_PREFIX, '')
70
+
71
+ /**
72
+ * Токенізує назву/слаг у множину значущих токенів (kebab + пробіли, без стоп-слів).
73
+ * @param {string} s назва або слаг для токенізації
74
+ * @returns {Set<string>} множина значущих токенів
75
+ */
76
+ export function tokenize(s) {
77
+ return new Set(
78
+ s
79
+ .toLowerCase()
80
+ .replace(RE_MD_EXT, '')
81
+ .replace(RE_TS_PREFIX, '')
82
+ .split(RE_TOKEN_SPLIT)
83
+ .filter((t) => t.length > 2 && !STOP.has(t))
84
+ )
85
+ }
86
+
87
+ /**
88
+ * Jaccard-схожість двох множин токенів.
89
+ * @param {Set<string>} a перша множина токенів
90
+ * @param {Set<string>} b друга множина токенів
91
+ * @returns {number} коефіцієнт Jaccard у діапазоні 0..1
92
+ */
93
+ export function jaccard(a, b) {
94
+ if (!a.size || !b.size) return 0
95
+ let inter = 0
96
+ for (const t of a) if (b.has(t)) inter++
97
+ return inter / (a.size + b.size - inter)
98
+ }
99
+
100
+ const MADR_SECTION = /^(Context and Problem|Considered Options|Decision Outcome|Consequences|More Information|report|summary|Attempt|Reason|Update)\b/i
101
+
102
+ /**
103
+ * Витягує заголовок драфта. Капчер пише `## ADR <title>` — він у пріоритеті
104
+ * (чернетка може мати контент-заголовки раніше або взагалі не мати ADR-рядка).
105
+ * Fallback-и: перший h1, що не є MADR-секцією, інакше '' (caller бере імʼя файлу).
106
+ * @param {string} body тіло чернетки
107
+ * @returns {string} заголовок або ''
108
+ */
109
+ export function draftTitle(body) {
110
+ const adr = body.match(RE_DRAFT_ADR_TITLE)
111
+ if (adr) return adr[1].trim()
112
+ for (const m of body.matchAll(/^#\s+(.+)$/gm)) {
113
+ if (!MADR_SECTION.test(m[1].trim())) return m[1].trim()
114
+ }
115
+ return ''
116
+ }
117
+
118
+ /**
119
+ * Детермінований no-decision гейт (харднінг #1). Чернетка, де у `Decision Outcome`
120
+ * рішення явно НЕ прийняте (transcript обірвався) — не варта окремого ADR: gold
121
+ * (sonnet) такі видаляє. Ловимо без LLM, щоб не покладатися на kind-judge малої моделі.
122
+ * @param {string} body тіло чернетки
123
+ * @returns {boolean} true якщо рішення не прийняте
124
+ */
125
+ export function isNoDecision(body) {
126
+ const m = body.match(RE_DECISION_SECTION)
127
+ if (!m) return false
128
+ // NB: JS \b не працює з кирилицею — покладаємось на пробіл/межі фрази без \b.
129
+ return RE_NO_DECISION.test(m[1])
130
+ }
131
+
132
+ /**
133
+ * Будує кандидати-ребра за лексичною схожістю.
134
+ * @param {{file:string, body:string}[]} drafts батч чернеток
135
+ * @param {string[]} cleanList clean basename-и
136
+ * @param {{simThreshold?:number, topKClean?:number}} [opts] поріг схожості та ліміт clean-кандидатів
137
+ * @returns {{dd:[number,number][], dc:[number,string][]}} ребра draft↔draft (dd) і draft↔clean (dc)
138
+ */
139
+ export function buildEdges(drafts, cleanList, opts = {}) {
140
+ const simThreshold = opts.simThreshold ?? 0.12
141
+ const topKClean = opts.topKClean ?? 3
142
+ const draftTok = drafts.map((d) => tokenize(`${d.file} ${draftTitle(d.body)}`))
143
+ const cleanTok = new Map(cleanList.map((c) => [c, tokenize(c)]))
144
+
145
+ const dd = []
146
+ for (let i = 0; i < drafts.length; i++) {
147
+ for (let j = i + 1; j < drafts.length; j++) {
148
+ if (jaccard(draftTok[i], draftTok[j]) >= simThreshold) dd.push([i, j])
149
+ }
150
+ }
151
+ const dc = []
152
+ for (let i = 0; i < drafts.length; i++) {
153
+ const scored = []
154
+ for (const [c, tok] of cleanTok) {
155
+ const s = jaccard(draftTok[i], tok)
156
+ if (s >= simThreshold) scored.push([c, s])
157
+ }
158
+ scored.sort((a, b) => b[1] - a[1])
159
+ for (const [c] of scored.slice(0, topKClean)) dc.push([i, c])
160
+ }
161
+ return { dd, dc }
162
+ }
163
+
164
+ // ─────────────────────────── LLM helper: tier cascade ──────────────────────────
165
+
166
+ const LOCAL = () => resolveModel('min')
167
+
168
+ /**
169
+ * Виклик LLM з локальним ретраєм і (опційно) хмарною ескалацією.
170
+ * @param {Array<{role:string,content:string}>} messages чат-повідомлення для LLM
171
+ * @param {(raw:string)=>any} parse валідатор (кидає на невалідному)
172
+ * @param {{label:string, allowCloud:boolean, attempts?:number, stats:object, maxTokens?:number}} cfg конфіг каскаду (мітка, дозвіл на хмару, спроби, лічильники, ліміт токенів)
173
+ * @returns {Promise<any>} результат parse
174
+ * @throws {Error} якщо всі спроби провалені
175
+ */
176
+ async function callWithCascade(messages, parse, cfg) {
177
+ const attempts = cfg.attempts ?? 2
178
+ let lastErr = null
179
+ for (let a = 0; a < attempts; a++) {
180
+ cfg.stats.localCalls++
181
+ const res = await runOneShot({
182
+ messages,
183
+ modelSpec: LOCAL(),
184
+ timeoutMs: 120_000,
185
+ caller: `adr-pipe:${cfg.label}`,
186
+ chain: cfg.chain ?? null
187
+ })
188
+ if (!res.error) {
189
+ try {
190
+ return parse(res.content)
191
+ } catch (error) {
192
+ lastErr = error // невалідний вихід → наступна спроба
193
+ continue
194
+ }
195
+ }
196
+ lastErr = new Error(res.error)
197
+ // infra (registry/session/модель недоступна) → ретрай локально марний.
198
+ if (RE_INFRA_ERROR.test(res.error)) break
199
+ }
200
+ if (cfg.allowCloud && CLOUD_MIN) {
201
+ cfg.stats.cloudCalls++
202
+ cfg.stats.escalations++
203
+ const res = await runOneShot({
204
+ messages,
205
+ modelSpec: CLOUD_MIN,
206
+ timeoutMs: 120_000,
207
+ caller: `adr-pipe:${cfg.label}:cloud`,
208
+ chain: cfg.chain ?? null
209
+ })
210
+ if (res.error) {
211
+ lastErr = new Error(res.error)
212
+ } else {
213
+ try {
214
+ return parse(res.content)
215
+ } catch (error) {
216
+ lastErr = error
217
+ }
218
+ }
219
+ }
220
+ cfg.stats.failures++
221
+ throw lastErr ?? new Error('callWithCascade: no result')
222
+ }
223
+
224
+ /**
225
+ * Витяг першого JSON-обʼєкта з raw-тексту.
226
+ * @param {string} raw сирий текст відповіді LLM
227
+ * @returns {any} розпарсений JSON-обʼєкт
228
+ * @throws {Error} якщо у тексті немає JSON-обʼєкта
229
+ */
230
+ function extractJson(raw) {
231
+ const s = raw.indexOf('{')
232
+ const e = raw.lastIndexOf('}')
233
+ if (s === -1 || e === -1) throw new Error('no JSON object')
234
+ return JSON.parse(raw.slice(s, e + 1))
235
+ }
236
+
237
+ // ─────────────────────────── Stage 1: edge-judge (LLM) ─────────────────────────
238
+
239
+ const EdgeSchema = z.object({
240
+ same: z.boolean(),
241
+ confidence: z.number().min(0).max(1),
242
+ reason: z.string().min(3).max(400)
243
+ })
244
+
245
+ const EDGE_SYS = `Ти порівнюєш два короткі записи архітектурних рішень (ADR). Визнач, чи вони описують ОДНЕ І ТЕ САМЕ рішення (одну тему/механізм, де другий лише уточнює/доповнює/продовжує перший), чи це РІЗНІ незалежні рішення.
246
+
247
+ Поверни ЛИШЕ JSON, без markdown:
248
+ { "same": true|false, "confidence": 0..1, "reason": "<коротко українською>" }
249
+
250
+ same=true ЛИШЕ якщо це по суті одне рішення (дублікат, уточнення, продовження тієї самої теми). Різні аспекти однієї підсистеми, але окремі рішення → same=false. Якщо сумніваєшся — false.`
251
+
252
+ /**
253
+ * Бінарний суддя «те саме рішення?» з self-consistency. Консервативний: `same`
254
+ * лише якщо ВСІ голоси кажуть same з confidence ≥ minConf. Харднінг #2: для
255
+ * draft↔draft (ризик over-merge) піднімаємо до 3 голосів і порога 0.6.
256
+ * @param {string} aTitle заголовок запису A
257
+ * @param {string} aBody тіло запису A
258
+ * @param {string} bTitle заголовок запису B
259
+ * @param {string} bBody тіло запису B
260
+ * @param {{allowCloud:boolean, votes?:number, stats:object}} cfg конфіг каскаду (дозвіл на хмару, голоси, лічильники)
261
+ * @param {{votes?:number, minConf?:number}} [vote] override голосів і порога на тип ребра
262
+ * @returns {{same:boolean, votes:object[]}} підтвердження same та сирі голоси
263
+ */
264
+ async function judgeEdge(aTitle, aBody, bTitle, bBody, cfg, vote = {}) {
265
+ const nVotes = vote.votes ?? cfg.votes ?? 2
266
+ const minConf = vote.minConf ?? 0.5
267
+ const user = `Запис A — "${aTitle}":\n${aBody.slice(0, 1500)}\n\n---\n\nЗапис B — "${bTitle}":\n${bBody.slice(0, 1500)}\n\nЦе одне й те саме рішення?`
268
+ const parse = raw => EdgeSchema.parse(extractJson(raw))
269
+ const votes = []
270
+ for (let v = 0; v < nVotes; v++) {
271
+ try {
272
+ votes.push(
273
+ await callWithCascade([{ role: 'system', content: EDGE_SYS }, { role: 'user', content: user }], parse, {
274
+ label: 'edge',
275
+ allowCloud: cfg.allowCloud,
276
+ stats: cfg.stats,
277
+ maxTokens: 300
278
+ })
279
+ )
280
+ } catch {
281
+ votes.push({ same: false, confidence: 0, reason: 'judge failed → conservative different' })
282
+ }
283
+ }
284
+ const sameCount = votes.filter(v => v.same && v.confidence >= minConf).length
285
+ return { same: sameCount === votes.length, votes }
286
+ }
287
+
288
+ // ─────────────────────────── Stage 1b: kind-judge (LLM) ────────────────────────
289
+
290
+ const KindSchema = z.object({
291
+ kind: z.enum(['standalone', 'trivial']),
292
+ reason: z.string().min(3).max(400)
293
+ })
294
+
295
+ const KIND_SYS = `Ти оцінюєш чернетку архітектурного рішення (ADR). Визнач:
296
+ - "standalone" — це самостійне рішення, варте збереження як decision record.
297
+ - "trivial" — порожнє / тривіальне / косметичне / без реального рішення, можна видалити.
298
+
299
+ Поверни ЛИШЕ JSON: { "kind": "standalone"|"trivial", "reason": "<коротко українською>" }
300
+ Якщо сумніваєшся — "standalone" (краще зберегти).`
301
+
302
+ async function judgeKind(title, body, cfg) {
303
+ const user = `Чернетка — "${title}":\n${body.slice(0, 2500)}\n\nstandalone чи trivial?`
304
+ const parse = raw => KindSchema.parse(extractJson(raw))
305
+ try {
306
+ return await callWithCascade([{ role: 'system', content: KIND_SYS }, { role: 'user', content: user }], parse, {
307
+ label: 'kind',
308
+ allowCloud: cfg.allowCloud,
309
+ stats: cfg.stats,
310
+ maxTokens: 200
311
+ })
312
+ } catch {
313
+ return { kind: 'standalone', reason: 'judge failed → conservative standalone' }
314
+ }
315
+ }
316
+
317
+ // ─────────────────────────── Stage 2: gen-MADR (LLM) ───────────────────────────
318
+
319
+ const MADR_HEADINGS = [
320
+ '## Context and Problem Statement',
321
+ '## Considered Options',
322
+ '## Decision Outcome',
323
+ '## More Information'
324
+ ]
325
+
326
+ /**
327
+ * Детермінований гейт якості згенерованого MADR.
328
+ * @param {string} content згенерований MADR-текст
329
+ * @returns {{ok:boolean, errors:string[]}} результат перевірки та перелік порушень
330
+ */
331
+ export function validateMadr(content) {
332
+ const errors = []
333
+ if (!content || content.length < 80) errors.push('too short')
334
+ if (RE_FENCE_LEAD.test(content) || RE_FENCE_TRAIL.test(content.trim())) errors.push('code-fence wrapper')
335
+ // OKF conformance: must have YAML frontmatter with type: ADR (not draft session: fields)
336
+ const fmMatch = RE_YAML_FRONTMATTER.exec(content)
337
+ if (!fmMatch || !RE_TYPE_ADR.test(fmMatch[1])) errors.push('missing OKF type: ADR frontmatter')
338
+ if (RE_SESSION.test(content)) errors.push('leaked session: field')
339
+ if (!RE_STATUS.test(content)) errors.push('missing Status')
340
+ if (!RE_DATE.test(content)) errors.push('missing/!ISO Date')
341
+ for (const h of MADR_HEADINGS) if (!content.includes(h)) errors.push(`missing heading ${h}`)
342
+ return { ok: errors.length === 0, errors }
343
+ }
344
+
345
+ // Інверсія форматування: модель НЕ генерує markdown-каркас MADR (заголовок,
346
+ // Status/Date, назви секцій, fallback-фрази, шаблон "Chosen option…") — усе це
347
+ // детерміновано, тому його будує JS у assembleMadr(). Модель повертає ЛИШЕ
348
+ // контент секцій як вузький JSON — те, що справді треба "витягти" з чернетки.
349
+ // Контракт: модель віддає ЛИШЕ зміст секцій (значення полів — markdown-проза зі
350
+ // збереженим inline-кодом). Каркас (заголовок, Status/Date, назви секцій ##,
351
+ // fallback-фрази, шаблон "Chosen option…") будує assembleMadr() детерміновано —
352
+ // тому модель НЕ пише жодних ## і не торкається заголовка/дати/статусу.
353
+ const GEN_SYS = `Ти витягуєш зміст архітектурного рішення з чернетки ADR у JSON. Нічого не вигадуй — бери лише те, що є в чернетці.
354
+
355
+ {
356
+ "context": "<2-4 речення: проблема й контекст рішення>",
357
+ "options": ["<розглянутий варіант>", "..."],
358
+ "chosen": "<обраний варіант, коротко>",
359
+ "rationale": "<чому обрано саме його>",
360
+ "good": ["<позитивний наслідок>", "..."],
361
+ "bad": ["<негативний наслідок>", "..."],
362
+ "more": "<файли/команди/API; можна кілька рядків і bullets>"
363
+ }
364
+
365
+ ВАЖЛИВО про значення полів:
366
+ - Зберігай inline-форматування: backticks навколо \`шляхів\`, \`назв.функцій()\`, \`команд\` — це частина змісту, не прибирай їх.
367
+ - НЕ додавай markdown-ЗАГОЛОВКИ (рядки з ##) і не пиши сам каркас (Status, Date, назви секцій) — лише зміст.
368
+ - Якщо чогось нема в чернетці — порожній рядок "" або порожній масив [].
369
+
370
+ Поверни ЛИШЕ JSON, без code-fence, без передмови.`
371
+
372
+ const slugify = (title) =>
373
+ title.toLowerCase().replace(RE_SLUG_NONWORD, '-').replace(RE_LEAD_HYPHEN, '').slice(0, 60).replace(RE_TRAIL_HYPHEN, '') || 'adr'
374
+
375
+ const RE_FNAME_DATE = /^(\d{2})(\d{2})(\d{2})-/
376
+ const RE_TRAIL_DOT = /\.+\s*$/
377
+
378
+ /**
379
+ * Детермінована ISO-дата для поля **Date:**. Пріоритет — `captured` frontmatter
380
+ * (перші 10 символів ISO-стемпа); fallback — timestamp-префікс імені файлу
381
+ * (`YYMMDD-…` → `20YY-MM-DD`). Каркас MADR не повинен залежати від LLM навіть тут.
382
+ * @param {string|undefined} captured значення поля captured (ISO-рядок)
383
+ * @param {string} [file] basename чернетки (для fallback-дати)
384
+ * @returns {string} ISO-дата `YYYY-MM-DD` або '' якщо нічого не вдалося витягти
385
+ */
386
+ export function madrDate(captured, file = '') {
387
+ const iso = (captured ?? '').slice(0, 10)
388
+ if (RE_DATE.test(`**Date:** ${iso}`)) return iso
389
+ const m = file.match(RE_FNAME_DATE)
390
+ return m ? `20${m[1]}-${m[2]}-${m[3]}` : ''
391
+ }
392
+
393
+ const secStr = (v) => (typeof v === 'string' ? v.trim() : v === null || v === undefined ? '' : String(v).trim())
394
+ const secArr = (v) => (Array.isArray(v) ? v.map(secStr).filter(Boolean) : secStr(v) ? [secStr(v)] : [])
395
+
396
+ /**
397
+ * Нормалізує сирий JSON-вивід gen-моделі у строгу форму секцій. Толерантна до
398
+ * дрібних відхилень малої моделі: рядок замість масиву → масив із одного елемента,
399
+ * число/null → рядок/порожньо, обрізає пробіли й порожні елементи.
400
+ * @param {any} obj розпарсений JSON-обʼєкт від моделі
401
+ * @returns {{context:string, options:string[], chosen:string, rationale:string, good:string[], bad:string[], more:string}} нормалізовані секції
402
+ */
403
+ export function normalizeSections(obj) {
404
+ return {
405
+ context: secStr(obj?.context),
406
+ options: secArr(obj?.options),
407
+ chosen: secStr(obj?.chosen),
408
+ rationale: secStr(obj?.rationale),
409
+ good: secArr(obj?.good),
410
+ bad: secArr(obj?.bad),
411
+ more: secStr(obj?.more)
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Детермінована збірка канонічного MADR 4.0.0 з заголовка, дати й секцій-контенту.
417
+ * Увесь каркас (Status, назви секцій, шаблон "Chosen option…", fallback-фрази,
418
+ * bullets) — тут, не в моделі. Заголовок і дата — JS-власність (draftTitle/captured),
419
+ * модель їх не торкається.
420
+ * @param {{title:string, date:string, sections:ReturnType<typeof normalizeSections>}} input заголовок, ISO-дата, нормалізовані секції
421
+ * @returns {string} готовий MADR-markdown
422
+ */
423
+ export function assembleMadr({ title, date, sections: s }) {
424
+ // Знімаємо кінцеву крапку контенту, бо шаблон додає свою (інакше "..").
425
+ const noDot = (x) => x.replace(RE_TRAIL_DOT, '')
426
+ const optBlock = s.options.length ? s.options.map((o) => `* ${o}`).join('\n') : 'Інші варіанти не обговорювалися.'
427
+ const cons = [...s.good.map((g) => `* Good, because ${noDot(g)}.`), ...s.bad.map((b) => `* Bad, because ${noDot(b)}.`)]
428
+ const consBlock = cons.length ? cons.join('\n') : 'Підтверджених наслідків не зафіксовано.'
429
+ const outcome = s.chosen
430
+ ? `Chosen option: "${s.chosen}"${s.rationale ? `, because ${noDot(s.rationale)}` : ''}.`
431
+ : s.rationale ? `${noDot(s.rationale)}.` : 'Рішення зафіксовано у чернетці.'
432
+ const titleYaml = title.replaceAll('\\', String.raw`\\`).replaceAll('"', String.raw`\"`)
433
+ return [
434
+ '---',
435
+ 'type: ADR',
436
+ `title: "${titleYaml}"`,
437
+ '---',
438
+ '',
439
+ '**Status:** Accepted',
440
+ `**Date:** ${date}`,
441
+ '',
442
+ '## Context and Problem Statement',
443
+ s.context || 'Контекст не зафіксовано у чернетці.',
444
+ '',
445
+ '## Considered Options',
446
+ optBlock,
447
+ '',
448
+ '## Decision Outcome',
449
+ outcome,
450
+ '',
451
+ '### Consequences',
452
+ consBlock,
453
+ '',
454
+ '## More Information',
455
+ s.more || 'Додаткової інформації не зафіксовано.',
456
+ ''
457
+ ].join('\n')
458
+ }
459
+
460
+ export async function genMadr(title, body, captured, cfg, file = '') {
461
+ const date = madrDate(captured, file)
462
+ const slug = slugify(title)
463
+ const user = `Чернетка "${title}":\n\n${body.slice(0, 4000)}\n\nВитягни зміст рішення у JSON.`
464
+ const parse = raw => {
465
+ const sections = normalizeSections(extractJson(raw))
466
+ if (!sections.context && !sections.chosen && !sections.rationale) {
467
+ throw new Error('empty extraction (no context/decision)')
468
+ }
469
+ const content = assembleMadr({ title, date, sections })
470
+ const v = validateMadr(content)
471
+ if (!v.ok) throw new Error(`MADR invalid: ${v.errors.join('; ')}`)
472
+ return content
473
+ }
474
+ try {
475
+ const content = await callWithCascade([{ role: 'system', content: GEN_SYS }, { role: 'user', content: user }], parse, {
476
+ label: 'gen',
477
+ allowCloud: cfg.allowCloud,
478
+ stats: cfg.stats,
479
+ attempts: 3,
480
+ maxTokens: 2048
481
+ })
482
+ return { content, slug, valid: true }
483
+ } catch (error) {
484
+ cfg.stats.madrInvalid++
485
+ return { content: null, slug, valid: false, error: error.message }
486
+ }
487
+ }
488
+
489
+ // ─────────────────────────── Stage 3: gen-merge (LLM) ──────────────────────────
490
+
491
+ // Каркас merge-блоку («## Update <date>») — теж JS-власність. Модель пише ЛИШЕ
492
+ // новий зміст-прозу; заголовок із детермінованою датою додає genMerge.
493
+ const MERGE_SYS = `Ти готуєш короткий додаток до існуючого ADR. Напиши ЛИШЕ новий зміст (проза/bullets), якого ще НЕМА в цільовому ADR — уточнення/виправлення/продовження. Стисло, українською, без заголовків, без code-fence, без передмови.`
494
+
495
+ async function genMerge(title, body, captured, targetTitle, cfg, file = '') {
496
+ const date = madrDate(captured, file)
497
+ const user = `Цільовий ADR: "${targetTitle}".\nЧернетка-доповнення "${title}" (${date}):\n${body.slice(0, 2500)}\n\nЛише новий зміст, без заголовка.`
498
+ const head = `## Update ${date}`
499
+ const parse = (raw) => {
500
+ const t = stripFence(raw)
501
+ // Захист від моделі, що все одно вписала свій заголовок: знімаємо його, щоб
502
+ // не подвоїти. Канонічний head додаємо детерміновано нижче.
503
+ const cleaned = RE_UPDATE_HEAD.test(t) ? t.replace(RE_UPDATE_HEAD_LINE, '').trim() : t
504
+ if (!cleaned) throw new Error('empty merge additions')
505
+ return `${head}\n\n${cleaned}`
506
+ }
507
+ try {
508
+ return await callWithCascade([{ role: 'system', content: MERGE_SYS }, { role: 'user', content: user }], parse, {
509
+ label: 'merge',
510
+ allowCloud: cfg.allowCloud,
511
+ stats: cfg.stats,
512
+ attempts: 2,
513
+ maxTokens: 1500
514
+ })
515
+ } catch {
516
+ return `${head}\n\n(доповнення з чернетки "${title}")`
517
+ }
518
+ }
519
+
520
+ // ─────────────────────────── union-find ────────────────────────────────────────
521
+
522
+ function makeDSU(n) {
523
+ const p = Array.from({ length: n }, (_, i) => i)
524
+ const find = (x) => (p[x] === x ? x : (p[x] = find(p[x])))
525
+ const union = (a, b) => { p[find(a)] = find(b) }
526
+ return { find, union }
527
+ }
528
+
529
+ const captureField = (body, field) => (body.match(new RegExp(`^${field}:\\s*(.+)$`, 'm')) ?? [])[1]?.trim()
530
+
531
+ /**
532
+ * No-op за замовчуванням для onProgress (коли caller не передав логер).
533
+ * @returns {void} нічого не робить
534
+ */
535
+ const noop = () => {
536
+ // навмисно порожньо: тихий fallback для onProgress
537
+ }
538
+
539
+ // ─────────────────────────── orchestrator ──────────────────────────────────────
540
+
541
+ /**
542
+ * Головний конвеєр. Повертає operations[] (контракт single-shot) + stats.
543
+ * @param {{file:string, body:string}[]} drafts батч чернеток
544
+ * @param {string[]} cleanList clean basename-и
545
+ * @param {{allowCloud?:boolean, votes?:number, onProgress?:(m:string)=>void, chainFactory?:typeof startChain}} [opts] хмарна ескалація, кількість голосів, колбек прогресу, фабрика ланцюжка (інжект для тестів)
546
+ * @returns {{operations:object[], stats:object, trace:object}} операції apply-ops, лічильники та діагностичний trace
547
+ */
548
+ export async function normalizePipeline(drafts, cleanList, opts = {}) {
549
+ // Один ланцюжок на весь прогін: edge-judge працює по ребрах ДО утворення
550
+ // кластерів, тож per-cluster chain не покрив би першу половину викликів;
551
+ // per-stage розріз аналітика бере з caller (`adr-pipe:<label>`).
552
+ const chain = (opts.chainFactory ?? startChain)({
553
+ kind: 'adr-normalize',
554
+ unit: `batch:${drafts.length}`,
555
+ cwd: process.cwd()
556
+ })
557
+ try {
558
+ const result = await normalizePipelineCore(drafts, cleanList, opts, chain)
559
+ chain.end({
560
+ outcome: result.stats.failures > 0 || result.stats.madrInvalid > 0 ? 'partial' : 'success',
561
+ extra: { drafts: drafts.length, ops: result.operations.length, stats: result.stats }
562
+ })
563
+ return result
564
+ } catch (error) {
565
+ chain.end({ outcome: 'fail', extra: { drafts: drafts.length, error: String(error.message ?? error).slice(0, 200) } })
566
+ throw error
567
+ }
568
+ }
569
+
570
+ /**
571
+ * Тіло конвеєра (chain належить обгортці normalizePipeline).
572
+ * @param {{file:string, body:string}[]} drafts батч чернеток
573
+ * @param {string[]} cleanList clean basename-и
574
+ * @param {{allowCloud?:boolean, votes?:number, onProgress?:(m:string)=>void}} opts опції прогону
575
+ * @param {object} chain chain handle
576
+ * @returns {Promise<{operations:object[], stats:object, trace:object}>} результат конвеєра
577
+ */
578
+ async function normalizePipelineCore(drafts, cleanList, opts, chain) {
579
+ const allowCloud = opts.allowCloud ?? false
580
+ const log = opts.onProgress ?? noop
581
+ const stats = { localCalls: 0, cloudCalls: 0, escalations: 0, failures: 0, madrInvalid: 0 }
582
+ const cfg = { allowCloud, votes: opts.votes ?? 2, stats, chain }
583
+
584
+ const titles = drafts.map((d) => draftTitle(d.body) || d.file.replace(RE_MD_EXT, ''))
585
+ const captured = drafts.map((d) => captureField(d.body, 'captured'))
586
+
587
+ // Харднінг #1: детермінований no-decision гейт. Такі драфти не кластеризуємо й
588
+ // не rewrite-имо — одразу delete (без LLM), як це робить gold.
589
+ const noDec = drafts.map((d) => isNoDecision(d.body))
590
+ if (noDec.some(Boolean)) log(`no-decision гейт: ${noDec.filter(Boolean).length} драфт(ів) → delete`)
591
+
592
+ // Stage 0: retrieval (ребра, що торкаються no-decision драфтів, відкидаємо)
593
+ const edges = buildEdges(drafts, cleanList)
594
+ const dd = edges.dd.filter(([i, j]) => !noDec[i] && !noDec[j])
595
+ const dc = edges.dc.filter(([i]) => !noDec[i])
596
+ log(`retrieval: ${dd.length} draft-draft ребер, ${dc.length} draft-clean кандидатів`)
597
+
598
+ // Stage 1: judge draft↔draft ребра (харднінг #2: 3 голоси, conf ≥ 0.6 проти over-merge)
599
+ const dsu = makeDSU(drafts.length)
600
+ const confirmedDD = []
601
+ for (const [i, j] of dd) {
602
+ const r = await judgeEdge(titles[i], drafts[i].body, titles[j], drafts[j].body, cfg, { votes: 3, minConf: 0.6 })
603
+ if (r.same) { dsu.union(i, j); confirmedDD.push([i, j]) }
604
+ }
605
+ log(`edge-judge: ${confirmedDD.length}/${dd.length} draft-draft ребер підтверджено`)
606
+
607
+ // Stage 1: judge draft↔clean → найкращий existing-target на драфт
608
+ const cleanTarget = Array.from({ length: drafts.length }).fill(null)
609
+ const dcByDraft = new Map()
610
+ for (const [i, c] of dc) { if (!dcByDraft.has(i)) dcByDraft.set(i, []); dcByDraft.get(i).push(c) }
611
+ for (const [i, cands] of dcByDraft) {
612
+ for (const c of cands) {
613
+ const cTitle = stripAdrName(c)
614
+ const r = await judgeEdge(titles[i], drafts[i].body, cTitle, cTitle, cfg)
615
+ if (r.same) { cleanTarget[i] = c; break }
616
+ }
617
+ }
618
+ log(`clean-match: ${cleanTarget.filter(Boolean).length} драфтів вже покриті clean-ADR`)
619
+
620
+ // Cluster (JS): групуємо за DSU
621
+ const clusters = new Map()
622
+ for (let i = 0; i < drafts.length; i++) {
623
+ const root = dsu.find(i)
624
+ if (!clusters.has(root)) clusters.set(root, [])
625
+ clusters.get(root).push(i)
626
+ }
627
+
628
+ const decision = Array.from({ length: drafts.length }).fill(null)
629
+ const operations = []
630
+
631
+ for (const [, members] of clusters) {
632
+ if (members.length > 1) {
633
+ // anchor — лише серед non-noDec (no-decision не може бути канонічним rewrite)
634
+ const live = members.filter((m) => !noDec[m])
635
+ // anchor = індекс із найдовшим drafts[idx].body.length; при рівності — перший
636
+ // зустрінутий (еквівалент reduce з `>=`, що зберігає поточний акумулятор a).
637
+ const candidates = live.length ? live : members
638
+ let anchor = candidates[0]
639
+ for (let k = 1; k < candidates.length; k++) {
640
+ if (drafts[candidates[k]].body.length > drafts[anchor].body.length) anchor = candidates[k]
641
+ }
642
+ decision[anchor] = { op: 'rewrite' }
643
+ for (const m of members) {
644
+ if (m === anchor) continue
645
+ decision[m] = noDec[m] ? { op: 'delete', reason: 'рішення не прийняте (transcript обірвався)' } : { op: 'merge-anchor', anchorIdx: anchor }
646
+ }
647
+ } else {
648
+ const i = members[0]
649
+ if (noDec[i]) decision[i] = { op: 'delete', reason: 'рішення не прийняте (transcript обірвався)' }
650
+ else if (cleanTarget[i]) decision[i] = { op: 'merge-existing', target: cleanTarget[i] }
651
+ else decision[i] = { op: 'kind' }
652
+ }
653
+ }
654
+
655
+ // одинаки без clean-target → kind-judge
656
+ for (let i = 0; i < drafts.length; i++) {
657
+ if (decision[i].op === 'kind') {
658
+ const k = await judgeKind(titles[i], drafts[i].body, cfg)
659
+ decision[i] = k.kind === 'trivial' ? { op: 'delete', reason: k.reason } : { op: 'rewrite' }
660
+ }
661
+ }
662
+
663
+ // Stage 2: gen-MADR для всіх rewrite (anchors + standalones)
664
+ const slugByIdx = Array.from({ length: drafts.length }).fill(null)
665
+ for (let i = 0; i < drafts.length; i++) {
666
+ if (decision[i].op !== 'rewrite') continue
667
+ const g = await genMadr(titles[i], drafts[i].body, captured[i], cfg, drafts[i].file)
668
+ slugByIdx[i] = g.slug
669
+ if (g.valid) {
670
+ operations.push({ op: 'rewrite', file: drafts[i].file, slug: g.slug, content: g.content })
671
+ } else {
672
+ decision[i] = { op: 'gen-failed' }
673
+ log(`gen-MADR FAILED для ${drafts[i].file}: ${g.error}`)
674
+ }
675
+ }
676
+
677
+ // Stage 3: merges
678
+ for (let i = 0; i < drafts.length; i++) {
679
+ const d = decision[i]
680
+ if (d.op === 'merge-anchor') {
681
+ const slug = slugByIdx[d.anchorIdx]
682
+ if (!slug) { log(`merge-anchor ${drafts[i].file}: anchor gen failed → skip`); continue }
683
+ const add = await genMerge(titles[i], drafts[i].body, captured[i], titles[d.anchorIdx], cfg, drafts[i].file)
684
+ operations.push({ op: 'merge-into', file: drafts[i].file, target: `${slug}.md`, additions: add })
685
+ } else if (d.op === 'merge-existing') {
686
+ const cTitle = stripAdrName(d.target)
687
+ const add = await genMerge(titles[i], drafts[i].body, captured[i], cTitle, cfg, drafts[i].file)
688
+ operations.push({ op: 'merge-into', file: drafts[i].file, target: d.target, additions: add })
689
+ } else if (d.op === 'delete') {
690
+ operations.push({ op: 'delete', file: drafts[i].file, reason: d.reason })
691
+ }
692
+ }
693
+
694
+ const trace = {
695
+ titles,
696
+ clusters: Array.from(clusters.values(), (m) => m.map((i) => drafts[i].file)),
697
+ cleanTargets: cleanTarget.map((c, i) => (c ? [drafts[i].file, c] : null)).filter(Boolean),
698
+ decisions: decision.map((d, i) => [drafts[i].file, d.op])
699
+ }
700
+ return { operations, stats, trace }
701
+ }