@1aboveio/skills 0.0.0-stage → 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 (633) hide show
  1. package/README.md +30 -2
  2. package/bin/cli.mjs +14 -0
  3. package/bin/select-core.mjs +172 -0
  4. package/package.json +146 -4
  5. package/skills/app-dev/airflow/LICENSE +3 -0
  6. package/skills/app-dev/airflow/SKILL.md +199 -0
  7. package/skills/app-dev/airflow/release-check.mjs +93 -0
  8. package/skills/app-dev/android-foundation/LICENSE +3 -0
  9. package/skills/app-dev/android-foundation/SKILL.md +192 -0
  10. package/skills/app-dev/android-foundation/assets/android-ci-job.yml +217 -0
  11. package/skills/app-dev/android-foundation/references/ci.md +87 -0
  12. package/skills/app-dev/android-foundation/references/gotchas.md +221 -0
  13. package/skills/app-dev/android-foundation/references/setup.md +164 -0
  14. package/skills/app-dev/android-foundation/release-check.mjs +93 -0
  15. package/skills/app-dev/android-foundation/scripts/device-run.sh +176 -0
  16. package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +172 -0
  17. package/skills/app-dev/app-debug/LICENSE +3 -0
  18. package/skills/app-dev/app-debug/SKILL.md +110 -0
  19. package/skills/app-dev/app-debug/references/common-errors.md +128 -0
  20. package/skills/app-dev/app-debug/release-check.mjs +93 -0
  21. package/skills/app-dev/better-auth/LICENSE +3 -0
  22. package/skills/app-dev/better-auth/SKILL.md +598 -0
  23. package/skills/app-dev/better-auth/references/feishu-api.md +270 -0
  24. package/skills/app-dev/better-auth/release-check.mjs +93 -0
  25. package/skills/app-dev/data-catalog/LICENSE +3 -0
  26. package/skills/app-dev/data-catalog/SKILL.md +204 -0
  27. package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
  28. package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +75 -0
  29. package/skills/app-dev/data-catalog/references/field-definitions.md +116 -0
  30. package/skills/app-dev/data-catalog/references/format.md +121 -0
  31. package/skills/app-dev/data-catalog/release-check.mjs +93 -0
  32. package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +36 -0
  33. package/skills/app-dev/data-catalog/scripts/data_catalog.py +1392 -0
  34. package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +117 -0
  35. package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +17 -0
  36. package/skills/app-dev/data-catalog/scripts/test_data_catalog.py +571 -0
  37. package/skills/app-dev/ios-foundation/LICENSE +3 -0
  38. package/skills/app-dev/ios-foundation/SKILL.md +184 -0
  39. package/skills/app-dev/ios-foundation/references/setup.md +243 -0
  40. package/skills/app-dev/ios-foundation/release-check.mjs +93 -0
  41. package/skills/app-dev/monorepo/LICENSE +3 -0
  42. package/skills/app-dev/monorepo/SKILL.md +462 -0
  43. package/skills/app-dev/monorepo/release-check.mjs +93 -0
  44. package/skills/app-dev/nextjs-fullstack/LICENSE +3 -0
  45. package/skills/app-dev/nextjs-fullstack/SKILL.md +211 -0
  46. package/skills/app-dev/nextjs-fullstack/conventions.md +318 -0
  47. package/skills/app-dev/nextjs-fullstack/frontend-conventions.md +61 -0
  48. package/skills/app-dev/nextjs-fullstack/nextjs16.md +287 -0
  49. package/skills/app-dev/nextjs-fullstack/release-check.mjs +93 -0
  50. package/skills/app-dev/nextjs-fullstack/server-actions.md +409 -0
  51. package/skills/app-dev/prisma-setup/LICENSE +3 -0
  52. package/skills/app-dev/prisma-setup/SKILL.md +181 -0
  53. package/skills/app-dev/prisma-setup/nextjs.md +258 -0
  54. package/skills/app-dev/prisma-setup/release-check.mjs +93 -0
  55. package/skills/app-dev/prisma-setup/turborepo.md +301 -0
  56. package/skills/app-dev/pyspark/LICENSE +3 -0
  57. package/skills/app-dev/pyspark/SKILL.md +127 -0
  58. package/skills/app-dev/pyspark/assets/templates/etl.py +748 -0
  59. package/skills/app-dev/pyspark/assets/templates/utils/__init__.py +1 -0
  60. package/skills/app-dev/pyspark/assets/templates/utils/hudi_metadata.py +14 -0
  61. package/skills/app-dev/pyspark/references/diagnosis-and-profiling.md +169 -0
  62. package/skills/app-dev/pyspark/references/etl-contract.md +129 -0
  63. package/skills/app-dev/pyspark/references/production-validation.md +131 -0
  64. package/skills/app-dev/pyspark/references/reconciliation.md +38 -0
  65. package/skills/app-dev/pyspark/references/transformation-design.md +190 -0
  66. package/skills/app-dev/pyspark/references/velocity-feature-calculation.md +193 -0
  67. package/skills/app-dev/pyspark/release-check.mjs +93 -0
  68. package/skills/app-dev/pyspark/scripts/spark_eventlog_summary.py +223 -0
  69. package/skills/app-dev/python-backend/LICENSE +3 -0
  70. package/skills/app-dev/python-backend/SKILL.md +325 -0
  71. package/skills/app-dev/python-backend/assets/uv-install.sh +48 -0
  72. package/skills/app-dev/python-backend/references/uv-installs.md +83 -0
  73. package/skills/app-dev/python-backend/release-check.mjs +93 -0
  74. package/skills/app-dev/shadcn/LICENSE +3 -0
  75. package/skills/app-dev/shadcn/SKILL.md +120 -0
  76. package/skills/app-dev/shadcn/assets/shadcn-small.png +0 -0
  77. package/skills/app-dev/shadcn/assets/shadcn.png +0 -0
  78. package/skills/app-dev/shadcn/cli.md +411 -0
  79. package/skills/app-dev/shadcn/customization.md +224 -0
  80. package/skills/app-dev/shadcn/mcp.md +101 -0
  81. package/skills/app-dev/shadcn/release-check.mjs +93 -0
  82. package/skills/app-dev/shadcn/rules/base-vs-radix.md +323 -0
  83. package/skills/app-dev/shadcn/rules/component-selection.md +67 -0
  84. package/skills/app-dev/shadcn/rules/composition.md +195 -0
  85. package/skills/app-dev/shadcn/rules/data-table.md +201 -0
  86. package/skills/app-dev/shadcn/rules/forms.md +255 -0
  87. package/skills/app-dev/shadcn/rules/icons.md +103 -0
  88. package/skills/app-dev/shadcn/rules/styling.md +167 -0
  89. package/skills/app-dev/zod-v4/LICENSE +3 -0
  90. package/skills/app-dev/zod-v4/SKILL.md +286 -0
  91. package/skills/app-dev/zod-v4/release-check.mjs +93 -0
  92. package/skills/cicd/cloud-build/LICENSE +3 -0
  93. package/skills/cicd/cloud-build/SKILL.md +707 -0
  94. package/skills/cicd/cloud-build/release-check.mjs +93 -0
  95. package/skills/cicd/cloud-debug/LICENSE +3 -0
  96. package/skills/cicd/cloud-debug/SKILL.md +315 -0
  97. package/skills/cicd/cloud-debug/references/build-failures.md +238 -0
  98. package/skills/cicd/cloud-debug/references/deploy-failures.md +376 -0
  99. package/skills/cicd/cloud-debug/references/pipeline-failures.md +378 -0
  100. package/skills/cicd/cloud-debug/release-check.mjs +93 -0
  101. package/skills/cicd/cloud-deploy/LICENSE +3 -0
  102. package/skills/cicd/cloud-deploy/SKILL.md +230 -0
  103. package/skills/cicd/cloud-deploy/references/config-templates.md +257 -0
  104. package/skills/cicd/cloud-deploy/release-check.mjs +93 -0
  105. package/skills/cicd/docker/LICENSE +3 -0
  106. package/skills/cicd/docker/SKILL.md +151 -0
  107. package/skills/cicd/docker/release-check.mjs +93 -0
  108. package/skills/cicd/github-actions/LICENSE +3 -0
  109. package/skills/cicd/github-actions/SKILL.md +111 -0
  110. package/skills/cicd/github-actions/references/audit-profile-optimize.md +150 -0
  111. package/skills/cicd/github-actions/references/ci-case-studies.md +141 -0
  112. package/skills/cicd/github-actions/references/conditional-ci.md +214 -0
  113. package/skills/cicd/github-actions/references/debugging.md +13 -0
  114. package/skills/cicd/github-actions/references/pipeline.md +87 -0
  115. package/skills/cicd/github-actions/references/post-deploy-and-publishing.md +33 -0
  116. package/skills/cicd/github-actions/references/runners.md +253 -0
  117. package/skills/cicd/github-actions/references/security.md +29 -0
  118. package/skills/cicd/github-actions/references/speed-and-audit.md +115 -0
  119. package/skills/cicd/github-actions/references/two-pass-reading.md +92 -0
  120. package/skills/cicd/github-actions/release-check.mjs +93 -0
  121. package/skills/cicd/github-actions/scripts/ci-run-audit-core.mjs +612 -0
  122. package/skills/cicd/github-actions/scripts/ci-run-audit.mjs +4 -0
  123. package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +637 -0
  124. package/skills/cicd/github-flow/LICENSE +3 -0
  125. package/skills/cicd/github-flow/SKILL.md +123 -0
  126. package/skills/cicd/github-flow/references/ci-conventions.md +14 -0
  127. package/skills/cicd/github-flow/release-check.mjs +93 -0
  128. package/skills/cicd/github-flow/scripts/flow-core.mjs +105 -0
  129. package/skills/cicd/github-flow/scripts/flow.mjs +81 -0
  130. package/skills/cicd/github-flow/scripts/flow.test.mjs +114 -0
  131. package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +117 -0
  132. package/skills/cicd/github-flow/scripts/persist-conventions.mjs +49 -0
  133. package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +108 -0
  134. package/skills/cicd/google-cloud/LICENSE +3 -0
  135. package/skills/cicd/google-cloud/SKILL.md +119 -0
  136. package/skills/cicd/google-cloud/references/gcs.md +469 -0
  137. package/skills/cicd/google-cloud/references/iam.md +451 -0
  138. package/skills/cicd/google-cloud/references/project.md +349 -0
  139. package/skills/cicd/google-cloud/references/secrets.md +336 -0
  140. package/skills/cicd/google-cloud/references/vpc.md +312 -0
  141. package/skills/cicd/google-cloud/release-check.mjs +93 -0
  142. package/skills/cicd/google-cloud/scripts/create-sa.sh +36 -0
  143. package/skills/cicd/google-cloud/scripts/gcp-config.sh +31 -0
  144. package/skills/cicd/google-cloud/scripts/grant-iap.sh +41 -0
  145. package/skills/cicd/google-cloud/scripts/setup-secrets.sh +48 -0
  146. package/skills/cicd/mergify/LICENSE +3 -0
  147. package/skills/cicd/mergify/SKILL.md +102 -0
  148. package/skills/cicd/mergify/assets/templates/mergify.yml +215 -0
  149. package/skills/cicd/mergify/assets/templates/ruleset.json +46 -0
  150. package/skills/cicd/mergify/references/branch-protection.md +282 -0
  151. package/skills/cicd/mergify/references/configuration.md +274 -0
  152. package/skills/cicd/mergify/references/diagnosis.md +109 -0
  153. package/skills/cicd/mergify/references/stacks.md +84 -0
  154. package/skills/cicd/mergify/references/traps.md +119 -0
  155. package/skills/cicd/mergify/references/watch-contract.md +274 -0
  156. package/skills/cicd/mergify/release-check.mjs +93 -0
  157. package/skills/cicd/mergify/scripts/audit-core.mjs +208 -0
  158. package/skills/cicd/mergify/scripts/audit.mjs +4 -0
  159. package/skills/cicd/mergify/scripts/audit.test.mjs +201 -0
  160. package/skills/cicd/mergify/scripts/entrypoints.test.mjs +106 -0
  161. package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +30 -0
  162. package/skills/cicd/mergify/scripts/stack-push-core.mjs +258 -0
  163. package/skills/cicd/mergify/scripts/stack-push.mjs +4 -0
  164. package/skills/cicd/mergify/scripts/stack-push.test.mjs +233 -0
  165. package/skills/cicd/mergify/scripts/watch-pr-delivery-core.mjs +1065 -0
  166. package/skills/cicd/mergify/scripts/watch-pr-delivery.mjs +4 -0
  167. package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +1826 -0
  168. package/skills/cicd/podman/LICENSE +3 -0
  169. package/skills/cicd/podman/SKILL.md +71 -0
  170. package/skills/cicd/podman/agents/openai.yaml +4 -0
  171. package/skills/cicd/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
  172. package/skills/cicd/podman/assets/templates/podman-service-override.conf +3 -0
  173. package/skills/cicd/podman/references/compose-compatibility.md +70 -0
  174. package/skills/cicd/podman/references/networking-and-ports.md +74 -0
  175. package/skills/cicd/podman/references/rootless-services-and-sockets.md +156 -0
  176. package/skills/cicd/podman/references/troubleshooting.md +98 -0
  177. package/skills/cicd/podman/release-check.mjs +93 -0
  178. package/skills/content/article-review/LICENSE +3 -0
  179. package/skills/content/article-review/SKILL.md +66 -0
  180. package/skills/content/article-review/references/report-format.md +68 -0
  181. package/skills/content/article-review/references/template-guide.md +79 -0
  182. package/skills/content/article-review/references/template-wechat-payments.md +125 -0
  183. package/skills/content/article-review/release-check.mjs +93 -0
  184. package/skills/content/article-to-image/LICENSE +3 -0
  185. package/skills/content/article-to-image/SKILL.md +91 -0
  186. package/skills/content/article-to-image/references/formats.md +53 -0
  187. package/skills/content/article-to-image/release-check.mjs +93 -0
  188. package/skills/content/flowchart-svg/LICENSE +3 -0
  189. package/skills/content/flowchart-svg/SKILL.md +43 -0
  190. package/skills/content/flowchart-svg/release-check.mjs +93 -0
  191. package/skills/content/flowchart-svg/scripts/export_png.sh +8 -0
  192. package/skills/content/image-gen/LICENSE +3 -0
  193. package/skills/content/image-gen/SKILL.md +192 -0
  194. package/skills/content/image-gen/release-check.mjs +93 -0
  195. package/skills/content/image-gen/scripts/credentials.mjs +217 -0
  196. package/skills/content/image-gen/scripts/credentials.test.mjs +212 -0
  197. package/skills/content/image-gen/scripts/generate.mjs +240 -0
  198. package/skills/content/image-gen/scripts/options.mjs +293 -0
  199. package/skills/content/image-gen/scripts/options.test.mjs +245 -0
  200. package/skills/content/mermaid/LICENSE +3 -0
  201. package/skills/content/mermaid/SKILL.md +635 -0
  202. package/skills/content/mermaid/release-check.mjs +93 -0
  203. package/skills/content/wechat-article-writer/LICENSE +3 -0
  204. package/skills/content/wechat-article-writer/SKILL.md +92 -0
  205. package/skills/content/wechat-article-writer/references/style-selector.md +133 -0
  206. package/skills/content/wechat-article-writer/references/writing-rules.md +152 -0
  207. package/skills/content/wechat-article-writer/release-check.mjs +93 -0
  208. package/skills/content/wechat-article-writer/templates/wechat-comparison.md +52 -0
  209. package/skills/content/wechat-article-writer/templates/wechat-howto.md +51 -0
  210. package/skills/content/wechat-article-writer/templates/wechat-insight.md +50 -0
  211. package/skills/content/wechat-article-writer/templates/wechat-pitfall.md +52 -0
  212. package/skills/content/wechat-publisher/LICENSE +3 -0
  213. package/skills/content/wechat-publisher/SKILL.md +171 -0
  214. package/skills/content/wechat-publisher/references/api.md +105 -0
  215. package/skills/content/wechat-publisher/references/layout-rules.md +57 -0
  216. package/skills/content/wechat-publisher/references/wechat-safe-template.html +86 -0
  217. package/skills/content/wechat-publisher/release-check.mjs +93 -0
  218. package/skills/content/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
  219. package/skills/content/wechat-publisher/scripts/publish.py +239 -0
  220. package/skills/content/wechat-search/LICENSE +3 -0
  221. package/skills/content/wechat-search/SKILL.md +211 -0
  222. package/skills/content/wechat-search/release-check.mjs +93 -0
  223. package/skills/content/wechat-search/scripts/start-chrome.sh +83 -0
  224. package/skills/content/xai-search/LICENSE +3 -0
  225. package/skills/content/xai-search/SKILL.md +79 -0
  226. package/skills/content/xai-search/release-check.mjs +93 -0
  227. package/skills/content/xai-search/scripts/xai_search.sh +187 -0
  228. package/skills/content/xai-search/tests/smoke_test.sh +36 -0
  229. package/skills/core/distill-writing/LICENSE +3 -0
  230. package/skills/core/distill-writing/SKILL.md +74 -0
  231. package/skills/core/distill-writing/references/extraction.md +95 -0
  232. package/skills/core/distill-writing/references/updating.md +46 -0
  233. package/skills/core/distill-writing/release-check.mjs +93 -0
  234. package/skills/core/doc-to-md/LICENSE +3 -0
  235. package/skills/core/doc-to-md/SKILL.md +78 -0
  236. package/skills/core/doc-to-md/release-check.mjs +93 -0
  237. package/skills/core/doc-to-md/scripts/convert.py +157 -0
  238. package/skills/core/editorial-review/LICENSE +3 -0
  239. package/skills/core/editorial-review/SKILL.md +79 -0
  240. package/skills/core/editorial-review/references/checklist.md +94 -0
  241. package/skills/core/editorial-review/release-check.mjs +93 -0
  242. package/skills/core/house-style/LICENSE +3 -0
  243. package/skills/core/house-style/SKILL.md +33 -0
  244. package/skills/core/house-style/references/defaults.md +66 -0
  245. package/skills/core/house-style/references/rules.md +267 -0
  246. package/skills/core/house-style/references/sources.md +27 -0
  247. package/skills/core/house-style/references/style-en.md +131 -0
  248. package/skills/core/house-style/references/style-zh.md +141 -0
  249. package/skills/core/house-style/references/terminology-zh.md +223 -0
  250. package/skills/core/house-style/release-check.mjs +93 -0
  251. package/skills/core/house-style/templates/brd.md +103 -0
  252. package/skills/core/house-style/templates/commercial-proposal.md +93 -0
  253. package/skills/core/house-style/templates/compliance-policy.md +109 -0
  254. package/skills/core/house-style/templates/gap-analysis.md +105 -0
  255. package/skills/core/house-style/templates/general.md +63 -0
  256. package/skills/core/house-style/templates/integration-guide.md +98 -0
  257. package/skills/core/house-style/templates/prd.md +81 -0
  258. package/skills/core/house-style/templates/risk-operations-procedure.md +94 -0
  259. package/skills/core/house-style/templates/technical-spec.md +96 -0
  260. package/skills/core/polish-cn/LICENSE +3 -0
  261. package/skills/core/polish-cn/SKILL.md +102 -0
  262. package/skills/core/polish-cn/references/brief.md +93 -0
  263. package/skills/core/polish-cn/references/models.md +76 -0
  264. package/skills/core/polish-cn/release-check.mjs +93 -0
  265. package/skills/core/polish-cn/scripts/polish-cn.test.mjs +244 -0
  266. package/skills/core/polish-cn/scripts/polish_blocks.py +489 -0
  267. package/skills/core/reg-parser/LICENSE +3 -0
  268. package/skills/core/reg-parser/SKILL.md +212 -0
  269. package/skills/core/reg-parser/references/checklist-schema.md +223 -0
  270. package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
  271. package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
  272. package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
  273. package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
  274. package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
  275. package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
  276. package/skills/core/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
  277. package/skills/core/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
  278. package/skills/core/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
  279. package/skills/core/reg-parser/references/mandates/visa-vars.md +205 -0
  280. package/skills/core/reg-parser/release-check.mjs +93 -0
  281. package/skills/core/reg-parser/scripts/compare_checklist.py +230 -0
  282. package/skills/core/reg-parser/scripts/dump_checklist.py +361 -0
  283. package/skills/core/reg-parser/scripts/preprocess-mandate.sh +187 -0
  284. package/skills/core/reg-parser/scripts/reg-parser.test.mjs +165 -0
  285. package/skills/core/reg-parser/scripts/test_quarantine.sh +105 -0
  286. package/skills/core/reg-parser/scripts/validate_checklist.py +563 -0
  287. package/skills/core/reg-parser/scripts/validate_mandate.py +273 -0
  288. package/skills/core/terminology/LICENSE +3 -0
  289. package/skills/core/terminology/SKILL.md +62 -0
  290. package/skills/core/terminology/references/format.md +50 -0
  291. package/skills/core/terminology/references/init.md +32 -0
  292. package/skills/core/terminology/release-check.mjs +93 -0
  293. package/skills/core/write-doc/LICENSE +3 -0
  294. package/skills/core/write-doc/SKILL.md +141 -0
  295. package/skills/core/write-doc/references/bilingual.md +60 -0
  296. package/skills/core/write-doc/release-check.mjs +93 -0
  297. package/skills/engineering/better-review/LICENSE +3 -0
  298. package/skills/engineering/better-review/SKILL.md +249 -0
  299. package/skills/engineering/better-review/agents/openai.yaml +9 -0
  300. package/skills/engineering/better-review/references/domain-hazards.md +53 -0
  301. package/skills/engineering/better-review/references/passes.md +147 -0
  302. package/skills/engineering/better-review/references/result.md +151 -0
  303. package/skills/engineering/better-review/release-check.mjs +93 -0
  304. package/skills/engineering/better-review/scripts/pr-context.mjs +212 -0
  305. package/skills/engineering/better-review/scripts/pr-context.test.mjs +168 -0
  306. package/skills/engineering/better-review/scripts/rereview-scope.mjs +503 -0
  307. package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +587 -0
  308. package/skills/engineering/better-review/scripts/scan-diff.mjs +365 -0
  309. package/skills/engineering/better-review/scripts/scan-diff.test.mjs +414 -0
  310. package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +96 -0
  311. package/skills/engineering/e2e-test/LICENSE +3 -0
  312. package/skills/engineering/e2e-test/SKILL.md +98 -0
  313. package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +24 -0
  314. package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
  315. package/skills/engineering/e2e-test/references/authoring/playwright-config.md +73 -0
  316. package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +144 -0
  317. package/skills/engineering/e2e-test/references/ci-integration.md +25 -0
  318. package/skills/engineering/e2e-test/references/ci-playwright-container.md +290 -0
  319. package/skills/engineering/e2e-test/references/presentation-sweep.md +104 -0
  320. package/skills/engineering/e2e-test/references/reviewing.md +41 -0
  321. package/skills/engineering/e2e-test/references/route-manifest.md +51 -0
  322. package/skills/engineering/e2e-test/release-check.mjs +93 -0
  323. package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
  324. package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
  325. package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +106 -0
  326. package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
  327. package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +117 -0
  328. package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
  329. package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +69 -0
  330. package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
  331. package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +98 -0
  332. package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +147 -0
  333. package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +71 -0
  334. package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
  335. package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +59 -0
  336. package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +82 -0
  337. package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +76 -0
  338. package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
  339. package/skills/engineering/engineering-runtime/LICENSE +3 -0
  340. package/skills/engineering/engineering-runtime/SKILL.md +11 -0
  341. package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
  342. package/skills/engineering/engineering-runtime/coherence/workflow.json +597 -0
  343. package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +68 -0
  344. package/skills/engineering/engineering-runtime/release-check.mjs +93 -0
  345. package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
  346. package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
  347. package/skills/engineering/engineering-runtime/scripts/invocation-policy.mjs +187 -0
  348. package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +95 -0
  349. package/skills/engineering/engineering-runtime/scripts/main-module.mjs +79 -0
  350. package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +288 -0
  351. package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
  352. package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
  353. package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
  354. package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
  355. package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +96 -0
  356. package/skills/engineering/engineering-runtime/scripts/review-completion.mjs +56 -0
  357. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +595 -0
  358. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +189 -0
  359. package/skills/engineering/engineering-runtime/scripts/yaml-mapping.mjs +18 -0
  360. package/skills/engineering/ensure-coverage/LICENSE +3 -0
  361. package/skills/engineering/ensure-coverage/SKILL.md +129 -0
  362. package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +92 -0
  363. package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +85 -0
  364. package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
  365. package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
  366. package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
  367. package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +19 -0
  368. package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
  369. package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +57 -0
  370. package/skills/engineering/ensure-coverage/references/depth/test-smells.md +39 -0
  371. package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +44 -0
  372. package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +110 -0
  373. package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +35 -0
  374. package/skills/engineering/ensure-coverage/references/presentation/axis.md +64 -0
  375. package/skills/engineering/ensure-coverage/references/process/audit-mode.md +27 -0
  376. package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
  377. package/skills/engineering/ensure-coverage/references/process/test-strategy.md +56 -0
  378. package/skills/engineering/ensure-coverage/release-check.mjs +93 -0
  379. package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +67 -0
  380. package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +140 -0
  381. package/skills/engineering/ensure-coverage/scripts/README.md +99 -0
  382. package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +182 -0
  383. package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +96 -0
  384. package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +105 -0
  385. package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +47 -0
  386. package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +137 -0
  387. package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +86 -0
  388. package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +674 -0
  389. package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +447 -0
  390. package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
  391. package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +552 -0
  392. package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +282 -0
  393. package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +289 -0
  394. package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
  395. package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +119 -0
  396. package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
  397. package/skills/engineering/golden-path/LICENSE +3 -0
  398. package/skills/engineering/golden-path/SKILL.md +230 -0
  399. package/skills/engineering/golden-path/agents/openai.yaml +3 -0
  400. package/skills/engineering/golden-path/assets/golden-paths.example.json +57 -0
  401. package/skills/engineering/golden-path/references/contract.md +239 -0
  402. package/skills/engineering/golden-path/references/migration.md +111 -0
  403. package/skills/engineering/golden-path/release-check.mjs +93 -0
  404. package/skills/engineering/golden-path/scripts/golden-path-core.mjs +1779 -0
  405. package/skills/engineering/golden-path/scripts/golden-path.mjs +6 -0
  406. package/skills/engineering/golden-path/scripts/golden-path.test.mjs +1457 -0
  407. package/skills/engineering/harness-runtime/LICENSE +3 -0
  408. package/skills/engineering/harness-runtime/SKILL.md +19 -0
  409. package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
  410. package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
  411. package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
  412. package/skills/engineering/harness-runtime/contracts.md +15 -0
  413. package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
  414. package/skills/engineering/harness-runtime/discover-models.test.mjs +363 -0
  415. package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
  416. package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
  417. package/skills/engineering/harness-runtime/harness-runtime.test.mjs +967 -0
  418. package/skills/engineering/harness-runtime/index.mjs +767 -0
  419. package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +829 -0
  420. package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
  421. package/skills/engineering/harness-runtime/model-catalog.test.mjs +366 -0
  422. package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
  423. package/skills/engineering/harness-runtime/references/model-catalog-seed.json +408 -0
  424. package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
  425. package/skills/engineering/harness-runtime/release-check.mjs +93 -0
  426. package/skills/engineering/resolve-issues/LICENSE +3 -0
  427. package/skills/engineering/resolve-issues/SKILL.md +250 -0
  428. package/skills/engineering/resolve-issues/agents/openai.yaml +9 -0
  429. package/skills/engineering/resolve-issues/plugin-hooks.json +17 -0
  430. package/skills/engineering/resolve-issues/references/canary.md +28 -0
  431. package/skills/engineering/resolve-issues/references/ci.md +105 -0
  432. package/skills/engineering/resolve-issues/references/done.md +25 -0
  433. package/skills/engineering/resolve-issues/references/dropbox.md +90 -0
  434. package/skills/engineering/resolve-issues/references/expire.md +318 -0
  435. package/skills/engineering/resolve-issues/references/exploration.md +202 -0
  436. package/skills/engineering/resolve-issues/references/implementation.md +303 -0
  437. package/skills/engineering/resolve-issues/references/preflight.md +445 -0
  438. package/skills/engineering/resolve-issues/references/review.md +228 -0
  439. package/skills/engineering/resolve-issues/references/shared-modules.md +44 -0
  440. package/skills/engineering/resolve-issues/references/task-plan.md +264 -0
  441. package/skills/engineering/resolve-issues/release-check.mjs +93 -0
  442. package/skills/engineering/resolve-issues/scripts/cleanup-runs.mjs +364 -0
  443. package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +280 -0
  444. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
  445. package/skills/engineering/resolve-issues/scripts/dropbox.mjs +473 -0
  446. package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +346 -0
  447. package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +98 -0
  448. package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +88 -0
  449. package/skills/engineering/resolve-issues/scripts/github-reviews.mjs +384 -0
  450. package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +264 -0
  451. package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +135 -0
  452. package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +79 -0
  453. package/skills/engineering/resolve-issues/scripts/issue-tree.mjs +162 -0
  454. package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +107 -0
  455. package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +14 -0
  456. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
  457. package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +149 -0
  458. package/skills/engineering/resolve-issues/scripts/next-actions.mjs +856 -0
  459. package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +915 -0
  460. package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +269 -0
  461. package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +156 -0
  462. package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +736 -0
  463. package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +448 -0
  464. package/skills/engineering/resolve-issues/scripts/ready-check.mjs +185 -0
  465. package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +217 -0
  466. package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +98 -0
  467. package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +91 -0
  468. package/skills/engineering/resolve-issues/scripts/review-verdict.mjs +509 -0
  469. package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +1060 -0
  470. package/skills/engineering/resolve-issues/scripts/size-check.mjs +492 -0
  471. package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +458 -0
  472. package/skills/engineering/resolve-release/LICENSE +3 -0
  473. package/skills/engineering/resolve-release/SKILL.md +215 -0
  474. package/skills/engineering/resolve-release/agents/openai.yaml +8 -0
  475. package/skills/engineering/resolve-release/flows/cloud-run-canary.md +13 -0
  476. package/skills/engineering/resolve-release/flows/cloud-run.md +7 -0
  477. package/skills/engineering/resolve-release/flows/root-tag-npm.md +13 -0
  478. package/skills/engineering/resolve-release/flows/workspace-npm.md +22 -0
  479. package/skills/engineering/resolve-release/references/canary.md +51 -0
  480. package/skills/engineering/resolve-release/references/candidate.md +41 -0
  481. package/skills/engineering/resolve-release/references/cut.md +131 -0
  482. package/skills/engineering/resolve-release/references/dark-launch.md +66 -0
  483. package/skills/engineering/resolve-release/references/flows.md +150 -0
  484. package/skills/engineering/resolve-release/references/preflight.md +154 -0
  485. package/skills/engineering/resolve-release/references/prepared-metadata.md +260 -0
  486. package/skills/engineering/resolve-release/references/promotion.md +82 -0
  487. package/skills/engineering/resolve-release/references/publish.md +232 -0
  488. package/skills/engineering/resolve-release/references/workspace-npm.md +103 -0
  489. package/skills/engineering/resolve-release/release-check.mjs +93 -0
  490. package/skills/engineering/resolve-release/scripts/apply.mjs +212 -0
  491. package/skills/engineering/resolve-release/scripts/apply.test.mjs +99 -0
  492. package/skills/engineering/resolve-release/scripts/dark-flags.mjs +134 -0
  493. package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +100 -0
  494. package/skills/engineering/resolve-release/scripts/flow.mjs +500 -0
  495. package/skills/engineering/resolve-release/scripts/flow.test.mjs +340 -0
  496. package/skills/engineering/resolve-release/scripts/green-head.mjs +231 -0
  497. package/skills/engineering/resolve-release/scripts/green-head.test.mjs +101 -0
  498. package/skills/engineering/resolve-release/scripts/npm-version-absence.mjs +138 -0
  499. package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +426 -0
  500. package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +659 -0
  501. package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +317 -0
  502. package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +291 -0
  503. package/skills/engineering/resolve-release/scripts/plan.mjs +806 -0
  504. package/skills/engineering/resolve-release/scripts/plan.test.mjs +428 -0
  505. package/skills/engineering/rush-issues/LICENSE +3 -0
  506. package/skills/engineering/rush-issues/SKILL.md +58 -0
  507. package/skills/engineering/rush-issues/agents/openai.yaml +8 -0
  508. package/skills/engineering/rush-issues/rehydrate.mjs +10 -0
  509. package/skills/engineering/rush-issues/release-check.mjs +93 -0
  510. package/skills/engineering/rush-release/LICENSE +3 -0
  511. package/skills/engineering/rush-release/SKILL.md +35 -0
  512. package/skills/engineering/rush-release/agents/openai.yaml +8 -0
  513. package/skills/engineering/rush-release/release-check.mjs +93 -0
  514. package/skills/engineering/test-quality/LICENSE +3 -0
  515. package/skills/engineering/test-quality/SKILL.md +79 -0
  516. package/skills/engineering/test-quality/references/audit.md +80 -0
  517. package/skills/engineering/test-quality/references/lint.md +24 -0
  518. package/skills/engineering/test-quality/references/principles.md +143 -0
  519. package/skills/engineering/test-quality/references/testing-conventions.md +9 -0
  520. package/skills/engineering/test-quality/release-check.mjs +93 -0
  521. package/skills/engineering/test-quality/scripts/lint-tests.mjs +574 -0
  522. package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +591 -0
  523. package/skills/engineering/test-quality/scripts/mock-policy-config.mjs +176 -0
  524. package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +119 -0
  525. package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +117 -0
  526. package/skills/engineering/test-quality/scripts/persist-conventions.mjs +17 -0
  527. package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +104 -0
  528. package/skills/risk-compliance/compliance-audit/LICENSE +3 -0
  529. package/skills/risk-compliance/compliance-audit/SKILL.md +439 -0
  530. package/skills/risk-compliance/compliance-audit/references/findings-schema.md +293 -0
  531. package/skills/risk-compliance/compliance-audit/references/normalization-rules.md +45 -0
  532. package/skills/risk-compliance/compliance-audit/references/vars-checklist.md +1068 -0
  533. package/skills/risk-compliance/compliance-audit/references/vars-findings-schema.md +398 -0
  534. package/skills/risk-compliance/compliance-audit/release-check.mjs +93 -0
  535. package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +14 -0
  536. package/skills/risk-compliance/compliance-audit/scripts/export_tracker_xlsx.py +221 -0
  537. package/skills/risk-compliance/compliance-audit/scripts/reconcile_tracker.py +458 -0
  538. package/skills/risk-compliance/compliance-audit/scripts/test_export_tracker_xlsx.py +97 -0
  539. package/skills/risk-compliance/compliance-audit/scripts/test_validate_tracker.py +157 -0
  540. package/skills/risk-compliance/compliance-audit/scripts/validate_tracker.py +829 -0
  541. package/skills/risk-compliance/contract-compare/LICENSE +3 -0
  542. package/skills/risk-compliance/contract-compare/SKILL.md +199 -0
  543. package/skills/risk-compliance/contract-compare/references/comparison-dimensions.md +209 -0
  544. package/skills/risk-compliance/contract-compare/release-check.mjs +93 -0
  545. package/skills/risk-compliance/contract-review/LICENSE +3 -0
  546. package/skills/risk-compliance/contract-review/SKILL.md +240 -0
  547. package/skills/risk-compliance/contract-review/references/review-criteria.md +223 -0
  548. package/skills/risk-compliance/contract-review/release-check.mjs +93 -0
  549. package/skills/risk-compliance/doc-authenticity/LICENSE +3 -0
  550. package/skills/risk-compliance/doc-authenticity/SKILL.md +160 -0
  551. package/skills/risk-compliance/doc-authenticity/agents/openai.yaml +8 -0
  552. package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +12 -0
  553. package/skills/risk-compliance/doc-authenticity/references/agreement.md +66 -0
  554. package/skills/risk-compliance/doc-authenticity/references/bank-statement.md +150 -0
  555. package/skills/risk-compliance/doc-authenticity/references/forensic-signals.md +157 -0
  556. package/skills/risk-compliance/doc-authenticity/references/image-signals.md +114 -0
  557. package/skills/risk-compliance/doc-authenticity/references/invoice.md +66 -0
  558. package/skills/risk-compliance/doc-authenticity/references/issuer-profiles.md +86 -0
  559. package/skills/risk-compliance/doc-authenticity/references/verdict-and-report.md +95 -0
  560. package/skills/risk-compliance/doc-authenticity/references/verdict.schema.json +81 -0
  561. package/skills/risk-compliance/doc-authenticity/release-check.mjs +93 -0
  562. package/skills/risk-compliance/doc-authenticity/scripts/image_forensics.py +294 -0
  563. package/skills/risk-compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
  564. package/skills/risk-compliance/doc-authenticity/scripts/validate_codes.py +224 -0
  565. package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
  566. package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +212 -0
  567. package/skills/risk-compliance/fraud-analysis/LICENSE +3 -0
  568. package/skills/risk-compliance/fraud-analysis/SKILL.md +114 -0
  569. package/skills/risk-compliance/fraud-analysis/references/archetypes/authorized-payment-scam.md +41 -0
  570. package/skills/risk-compliance/fraud-analysis/references/archetypes/first-party-fraud.md +44 -0
  571. package/skills/risk-compliance/fraud-analysis/references/archetypes/third-party-fraud.md +27 -0
  572. package/skills/risk-compliance/fraud-analysis/references/contexts/bank-transfer.md +24 -0
  573. package/skills/risk-compliance/fraud-analysis/references/contexts/card-payment.md +30 -0
  574. package/skills/risk-compliance/fraud-analysis/references/contexts/payment-collection.md +20 -0
  575. package/skills/risk-compliance/fraud-analysis/references/contexts/payout.md +20 -0
  576. package/skills/risk-compliance/fraud-analysis/references/feature-engineering.md +158 -0
  577. package/skills/risk-compliance/fraud-analysis/references/mechanisms/account-takeover.md +36 -0
  578. package/skills/risk-compliance/fraud-analysis/references/report-rationale.md +45 -0
  579. package/skills/risk-compliance/fraud-analysis/references/report-template.md +190 -0
  580. package/skills/risk-compliance/fraud-analysis/references/review-checklist.md +175 -0
  581. package/skills/risk-compliance/fraud-analysis/references/taxonomy.md +79 -0
  582. package/skills/risk-compliance/fraud-analysis/references/terminology.md +108 -0
  583. package/skills/risk-compliance/fraud-analysis/references/workflow.md +175 -0
  584. package/skills/risk-compliance/fraud-analysis/release-check.mjs +93 -0
  585. package/skills/risk-compliance/payment-analysis/LICENSE +3 -0
  586. package/skills/risk-compliance/payment-analysis/SKILL.md +180 -0
  587. package/skills/risk-compliance/payment-analysis/references/auth-rate-actions.md +30 -0
  588. package/skills/risk-compliance/payment-analysis/references/chargebacks.md +208 -0
  589. package/skills/risk-compliance/payment-analysis/references/chinese-polish.md +51 -0
  590. package/skills/risk-compliance/payment-analysis/references/event-layers.md +127 -0
  591. package/skills/risk-compliance/payment-analysis/references/fx.md +59 -0
  592. package/skills/risk-compliance/payment-analysis/references/journey.md +79 -0
  593. package/skills/risk-compliance/payment-analysis/references/metrics.md +67 -0
  594. package/skills/risk-compliance/payment-analysis/references/report-template.md +119 -0
  595. package/skills/risk-compliance/payment-analysis/references/terminology.md +95 -0
  596. package/skills/risk-compliance/payment-analysis/references/visualization.md +56 -0
  597. package/skills/risk-compliance/payment-analysis/release-check.mjs +93 -0
  598. package/skills/risk-compliance/report-writing/LICENSE +3 -0
  599. package/skills/risk-compliance/report-writing/SKILL.md +220 -0
  600. package/skills/risk-compliance/report-writing/references/audit-report-template.md +121 -0
  601. package/skills/risk-compliance/report-writing/references/external-assessment-template.md +167 -0
  602. package/skills/risk-compliance/report-writing/references/management-report-template.md +145 -0
  603. package/skills/risk-compliance/report-writing/references/vars-report-template.md +224 -0
  604. package/skills/risk-compliance/report-writing/release-check.mjs +93 -0
  605. package/skills/risk-compliance/similar-domain/LICENSE +3 -0
  606. package/skills/risk-compliance/similar-domain/SKILL.md +203 -0
  607. package/skills/risk-compliance/similar-domain/references/entities.md +67 -0
  608. package/skills/risk-compliance/similar-domain/references/fingerprints.md +134 -0
  609. package/skills/risk-compliance/similar-domain/references/pivots.md +82 -0
  610. package/skills/risk-compliance/similar-domain/references/report-template.md +93 -0
  611. package/skills/risk-compliance/similar-domain/references/scoring.md +130 -0
  612. package/skills/risk-compliance/similar-domain/references/terminology.md +41 -0
  613. package/skills/risk-compliance/similar-domain/references/workflow.md +85 -0
  614. package/skills/risk-compliance/similar-domain/release-check.mjs +93 -0
  615. package/skills/risk-compliance/tld-detection/LICENSE +3 -0
  616. package/skills/risk-compliance/tld-detection/SKILL.md +245 -0
  617. package/skills/risk-compliance/tld-detection/agents/openai.yaml +9 -0
  618. package/skills/risk-compliance/tld-detection/references/chinese-polish.md +55 -0
  619. package/skills/risk-compliance/tld-detection/references/clean.md +51 -0
  620. package/skills/risk-compliance/tld-detection/references/clustering.md +235 -0
  621. package/skills/risk-compliance/tld-detection/references/decision.md +189 -0
  622. package/skills/risk-compliance/tld-detection/references/fx-conversion.md +232 -0
  623. package/skills/risk-compliance/tld-detection/references/report-template.md +272 -0
  624. package/skills/risk-compliance/tld-detection/references/streams.md +141 -0
  625. package/skills/risk-compliance/tld-detection/references/terminology.md +95 -0
  626. package/skills/risk-compliance/tld-detection/references/workflow.md +95 -0
  627. package/skills/risk-compliance/tld-detection/release-check.mjs +93 -0
  628. package/skills/risk-compliance/tld-detection/scripts/detect_ladders.py +390 -0
  629. package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +14 -0
  630. package/skills/risk-compliance/tld-detection/scripts/detect_streams.py +650 -0
  631. package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +14 -0
  632. package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +134 -0
  633. package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +520 -0
@@ -0,0 +1,176 @@
1
+ // mock-policy-config — project-agnostic classifier for the `mock-internal-seam`
2
+ // lint rule. The engine is invariant; the project's topology is *declared*, not
3
+ // hardcoded. This is the "externals-allowlist inversion": you cannot enumerate
4
+ // every internal seam (unbounded, per-project), but the set of things that may
5
+ // LEGITIMATELY be faked is small, stable, and known — third-party HTTP, the
6
+ // clock, randomness, the runtime/stdlib. So we flip the question: a mock whose
7
+ // target resolves to *first-party* code is a candidate gap; anything on the
8
+ // declared externals allowlist (or the stdlib) is exempt. This makes the
9
+ // "real internals, faked externals, nothing between" policy (SKILL.md principle 3)
10
+ // decidable from config rather than from a baked-in path regex.
11
+ //
12
+ // Per-project facts come from a `coverage.config.json` (or `.coverage.config.json`)
13
+ // at the repo root, under a `mockPolicy` key. The config only *declares topology*
14
+ // (a monorepo's own package scope, generated dirs to exempt) — it does NOT gate
15
+ // whether the rule runs. Over-mock is ZERO-TOLERANCE: the gate is default-on and
16
+ // works with zero config on a conventional `@/`-aliased repo. There is no
17
+ // `enabled:false` off switch and no inline waiver.
18
+
19
+ import fs from 'node:fs'
20
+ import path from 'node:path'
21
+
22
+ /** Generic defaults — safe for any repo; tune topology via coverage.config.json. */
23
+ export const DEFAULT_MOCK_POLICY = {
24
+ // Default-ON. Zero-tolerance: a project cannot turn the over-mock gate off via
25
+ // config; `enabled` is retained only so a config that sets it is accepted, but
26
+ // the rule is default-on (defaultOn:true) regardless. There is no opt-out.
27
+ enabled: true,
28
+ // Import-specifier prefixes that denote first-party app source. `@/` and `~/`
29
+ // are near-universal TS path aliases for "this app's src".
30
+ firstPartyAliasPrefixes: ['@/', '~/'],
31
+ // Bare package names (exact or prefix) that are actually first-party workspace
32
+ // packages — e.g. a monorepo's own scope `@acme/`. Declared per project.
33
+ firstPartyPackages: [],
34
+ // Regex sources (strings) for specifiers that ARE legitimately external and so
35
+ // exempt — third-party APIs/SDKs a project wants to name explicitly. Bare npm
36
+ // packages are already treated as external by default; this is for the rare
37
+ // case you must override (or to exempt a first-party-looking alias).
38
+ externals: [],
39
+ // Path segments that mark a relative import as a test util / fixture / mock,
40
+ // NOT an internal seam — mocking those is not over-mocking.
41
+ testUtilHints: [
42
+ '__mocks__', '__fixtures__', 'fixtures', 'mocks', 'helpers',
43
+ 'test-utils', 'testing', 'support', 'stubs', 'factories',
44
+ ],
45
+ }
46
+
47
+ /**
48
+ * Compile externals regex sources once and attach them as a genuinely
49
+ * non-enumerable cache, so the compiled RegExp[] never leaks into a
50
+ * `JSON.stringify(policy)` (where it would serialize to a useless `{}`) or a
51
+ * `deepEqual` over the policy's declared fields.
52
+ */
53
+ function compile(policy) {
54
+ const externalsRe = (policy.externals || []).map((src) => {
55
+ try { return new RegExp(src) } catch { return null }
56
+ }).filter(Boolean)
57
+ const compiled = { ...policy }
58
+ Object.defineProperty(compiled, '_externalsRe', { value: externalsRe, enumerable: false })
59
+ return compiled
60
+ }
61
+
62
+ /**
63
+ * Merge a project's `mockPolicy` over the defaults and compile it. Pure given
64
+ * the override object (no fs); use loadMockPolicy() to read from disk.
65
+ */
66
+ export function resolveMockPolicy(override = {}) {
67
+ const merged = {
68
+ ...DEFAULT_MOCK_POLICY,
69
+ ...override,
70
+ // arrays replace wholesale when provided, else inherit the default
71
+ firstPartyAliasPrefixes: override.firstPartyAliasPrefixes ?? DEFAULT_MOCK_POLICY.firstPartyAliasPrefixes,
72
+ firstPartyPackages: override.firstPartyPackages ?? DEFAULT_MOCK_POLICY.firstPartyPackages,
73
+ externals: override.externals ?? DEFAULT_MOCK_POLICY.externals,
74
+ testUtilHints: override.testUtilHints ?? DEFAULT_MOCK_POLICY.testUtilHints,
75
+ }
76
+ return compile(merged)
77
+ }
78
+
79
+ /** Non-fatal warning sink (stderr). Kept here so both loaders warn identically. */
80
+ function warn(msg) {
81
+ process.stderr.write(`lint-tests: ${msg}\n`)
82
+ }
83
+
84
+ /**
85
+ * Read+resolve `mockPolicy` from one config file. Returns the resolved policy,
86
+ * or `null` when the file does not exist (so the dir-search can fall through).
87
+ * A *malformed* file resolves to defaults AND warns — a silent fallback would let
88
+ * a typo'd config that meant `enabled:true` masquerade as a clean run (finding #2).
89
+ */
90
+ function readConfigFile(p) {
91
+ if (!fs.existsSync(p)) return null
92
+ try {
93
+ const cfg = JSON.parse(fs.readFileSync(p, 'utf8'))
94
+ return resolveMockPolicy(cfg.mockPolicy ?? {})
95
+ } catch (e) {
96
+ warn(`ignoring malformed ${p} (${e.message}); mock-policy running on defaults`)
97
+ return resolveMockPolicy({})
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Discover `coverage.config.json` / `.coverage.config.json` in rootDir and resolve
103
+ * its `mockPolicy`. Returns the compiled default policy when absent/unparsable
104
+ * (never throws — a missing config must not break the gate).
105
+ */
106
+ export function loadMockPolicy(rootDir = process.cwd()) {
107
+ for (const name of ['coverage.config.json', '.coverage.config.json']) {
108
+ const got = readConfigFile(path.join(rootDir, name))
109
+ if (got) return got
110
+ }
111
+ return resolveMockPolicy({})
112
+ }
113
+
114
+ /**
115
+ * Resolve the policy for an explicit `--config <file>`. Reads THAT file (finding
116
+ * #1: the old caller passed only its dirname, so a non-standard filename was
117
+ * silently discarded and the gate ran on defaults). Falls back to dir-discovery
118
+ * when no file is given, and WARNS (non-fatal) when the named file is missing —
119
+ * a declared config that doesn't apply must never look like a clean pass.
120
+ */
121
+ export function loadMockPolicyFromFile(configFile, rootDir = process.cwd()) {
122
+ if (!configFile) return loadMockPolicy(rootDir)
123
+ const got = readConfigFile(configFile)
124
+ if (got) return got
125
+ warn(`--config ${configFile} not found; mock-policy running on defaults`)
126
+ return resolveMockPolicy({})
127
+ }
128
+
129
+ /**
130
+ * Extract the mocked module specifier from a (comment-stripped) line of test
131
+ * code, or null. Covers the JS/TS module-mock front-ends: `vi.mock`/`vi.doMock`,
132
+ * `jest.mock`/`jest.doMock`, `vitest.mock`. Other ecosystems (e.g. Python
133
+ * `patch('a.b.c')`) are a future adapter — keep one matcher per ecosystem so the
134
+ * core classify logic stays shared. Returns the FIRST string argument only.
135
+ */
136
+ export function extractMockTarget(codeLine) {
137
+ const m = /\b(?:vi|jest|vitest)\s*\.\s*(?:mock|doMock)\s*\(\s*(['"`])([^'"`]+)\1/.exec(codeLine || '')
138
+ return m ? m[2] : null
139
+ }
140
+
141
+ /**
142
+ * Classify a mock target as an internal seam (a gap) or an allowed external.
143
+ * Decidable given the policy — no fs, no module resolution at runtime; the
144
+ * project's declared topology supplies the facts.
145
+ *
146
+ * Precedence: declared externals > stdlib > relative(util vs source) >
147
+ * first-party alias > first-party package > bare package (external default).
148
+ */
149
+ export function classifyMockTarget(target, policy = DEFAULT_MOCK_POLICY) {
150
+ const p = policy._externalsRe ? policy : compile(policy)
151
+ if (!target) return { internal: false, reason: 'no target' }
152
+
153
+ for (const re of p._externalsRe) {
154
+ if (re.test(target)) return { internal: false, reason: 'declared external' }
155
+ }
156
+ if (target.startsWith('node:')) return { internal: false, reason: 'node builtin' }
157
+
158
+ if (target.startsWith('.')) {
159
+ const segs = target.split('/')
160
+ if (segs.some((s) => p.testUtilHints.includes(s))) {
161
+ return { internal: false, reason: 'relative test util/fixture/mock' }
162
+ }
163
+ return { internal: true, reason: 'relative import into first-party source' }
164
+ }
165
+
166
+ for (const pre of p.firstPartyAliasPrefixes) {
167
+ if (target.startsWith(pre)) return { internal: true, reason: `first-party alias "${pre}"` }
168
+ }
169
+ for (const fp of p.firstPartyPackages) {
170
+ const base = fp.endsWith('/') ? fp.slice(0, -1) : fp
171
+ if (target === base || target.startsWith(`${base}/`)) {
172
+ return { internal: true, reason: `first-party package "${fp}"` }
173
+ }
174
+ }
175
+ return { internal: false, reason: 'external package' }
176
+ }
@@ -0,0 +1,119 @@
1
+ // Tests for the mock-policy classifier (pure; one fs case via a temp dir).
2
+ import { test } from 'node:test'
3
+ import assert from 'node:assert/strict'
4
+ import fs from 'node:fs'
5
+ import os from 'node:os'
6
+ import path from 'node:path'
7
+
8
+ import {
9
+ DEFAULT_MOCK_POLICY,
10
+ resolveMockPolicy,
11
+ loadMockPolicy,
12
+ loadMockPolicyFromFile,
13
+ extractMockTarget,
14
+ classifyMockTarget,
15
+ } from './mock-policy-config.mjs'
16
+
17
+ test('default policy is zero-tolerance: default-on, no waiver tag', () => {
18
+ assert.equal(DEFAULT_MOCK_POLICY.enabled, true)
19
+ // the inline-waiver escape hatch is gone
20
+ assert.equal(DEFAULT_MOCK_POLICY.waiverTag, undefined)
21
+ })
22
+
23
+ test('extractMockTarget pulls the specifier from vi/jest/vitest mock+doMock', () => {
24
+ assert.equal(extractMockTarget("vi." + "mock('@/lib/x')"), '@/lib/x')
25
+ assert.equal(extractMockTarget('jest.' + 'mock("pkg")'), 'pkg')
26
+ assert.equal(extractMockTarget('vi.' + 'doMock(`@/a/b`)'), '@/a/b')
27
+ assert.equal(extractMockTarget('vitest.' + 'mock("./rel")'), './rel')
28
+ assert.equal(extractMockTarget('const x = mockThing()'), null) // bare mock() is not a module mock
29
+ assert.equal(extractMockTarget('expect(x).toBe(1)'), null)
30
+ })
31
+
32
+ test('classify: first-party alias @/ and ~/ are internal seams (the incident case)', () => {
33
+ const p = resolveMockPolicy({})
34
+ assert.equal(classifyMockTarget('@/lib/org-allowlist-client', p).internal, true)
35
+ assert.equal(classifyMockTarget('~/services/cp', p).internal, true)
36
+ })
37
+
38
+ test('classify: stdlib and third-party packages are external (exempt)', () => {
39
+ const p = resolveMockPolicy({})
40
+ assert.equal(classifyMockTarget('node:fs', p).internal, false)
41
+ assert.equal(classifyMockTarget('react', p).internal, false)
42
+ assert.equal(classifyMockTarget('@playwright/test', p).internal, false)
43
+ })
44
+
45
+ test('classify: relative import into source is internal; into a test util/fixture is not', () => {
46
+ const p = resolveMockPolicy({})
47
+ assert.equal(classifyMockTarget('../services/payments', p).internal, true)
48
+ assert.equal(classifyMockTarget('./helpers/operator-session-store', p).internal, false)
49
+ assert.equal(classifyMockTarget('../__mocks__/cp', p).internal, false)
50
+ assert.equal(classifyMockTarget('../fixtures/data', p).internal, false)
51
+ })
52
+
53
+ test('classify: declared first-party workspace package is internal', () => {
54
+ const p = resolveMockPolicy({ firstPartyPackages: ['@acme/'] })
55
+ assert.equal(classifyMockTarget('@acme/db', p).internal, true)
56
+ assert.equal(classifyMockTarget('@acme', p).internal, true)
57
+ assert.equal(classifyMockTarget('@other/db', p).internal, false)
58
+ })
59
+
60
+ test('classify: declared externals allowlist exempts a first-party-looking target', () => {
61
+ const p = resolveMockPolicy({ externals: ['^@/generated/'] })
62
+ assert.equal(classifyMockTarget('@/generated/openapi', p).internal, false) // exempted
63
+ assert.equal(classifyMockTarget('@/lib/x', p).internal, true) // still flagged
64
+ })
65
+
66
+ test('compiled _externalsRe is non-enumerable: does not leak into JSON / enumeration', () => {
67
+ const p = resolveMockPolicy({ externals: ['^@/generated/'] })
68
+ // the compiled RegExp cache works...
69
+ assert.equal(classifyMockTarget('@/generated/openapi', p).internal, false)
70
+ // ...but is hidden from enumeration and serialization
71
+ assert.ok(!Object.keys(p).includes('_externalsRe'))
72
+ assert.equal(JSON.parse(JSON.stringify(p))._externalsRe, undefined)
73
+ })
74
+
75
+ test('loadMockPolicy reads coverage.config.json topology, defaults to on with no config', () => {
76
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mpc-'))
77
+ // no config → zero-tolerance default (on), conventional topology
78
+ assert.equal(loadMockPolicy(dir).enabled, true)
79
+ // with config → declared topology is merged in (config declares topology, not on/off)
80
+ fs.writeFileSync(
81
+ path.join(dir, 'coverage.config.json'),
82
+ JSON.stringify({ mockPolicy: { firstPartyPackages: ['@acme/'] } }),
83
+ )
84
+ const p = loadMockPolicy(dir)
85
+ assert.equal(p.enabled, true)
86
+ assert.deepEqual(p.firstPartyPackages, ['@acme/'])
87
+ // inherited default array still present
88
+ assert.ok(p.firstPartyAliasPrefixes.includes('@/'))
89
+ })
90
+
91
+ test('loadMockPolicy never throws on malformed config (and stays on)', () => {
92
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mpc-'))
93
+ fs.writeFileSync(path.join(dir, 'coverage.config.json'), '{ not json')
94
+ assert.equal(loadMockPolicy(dir).enabled, true)
95
+ })
96
+
97
+ test('loadMockPolicyFromFile reads the NAMED file (finding #1: not just its dirname)', () => {
98
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mpc-'))
99
+ const file = path.join(dir, 'team-coverage.json') // deliberately non-standard name
100
+ fs.writeFileSync(file, JSON.stringify({ mockPolicy: { enabled: true, externals: ['^@/generated/'] } }))
101
+ const p = loadMockPolicyFromFile(file)
102
+ assert.equal(p.enabled, true)
103
+ // the declared externals must actually apply (proof the file was read, not defaults)
104
+ assert.equal(classifyMockTarget('@/generated/openapi', p).internal, false)
105
+ assert.equal(classifyMockTarget('@/lib/auth', p).internal, true)
106
+ })
107
+
108
+ test('loadMockPolicyFromFile falls back to defaults when the named file is missing', () => {
109
+ // finding #1: a declared config that does not apply must not look like a clean pass.
110
+ // (It warns on stderr; here we assert the zero-tolerance default — gate stays ON.)
111
+ const p = loadMockPolicyFromFile(path.join(os.tmpdir(), 'definitely-absent-config-xyz.json'))
112
+ assert.equal(p.enabled, true)
113
+ })
114
+
115
+ test('loadMockPolicyFromFile with no argument discovers coverage.config.json in cwd', () => {
116
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'mpc-'))
117
+ fs.writeFileSync(path.join(dir, 'coverage.config.json'), JSON.stringify({ mockPolicy: { enabled: true } }))
118
+ assert.equal(loadMockPolicyFromFile(undefined, dir).enabled, true)
119
+ })
@@ -0,0 +1,117 @@
1
+ // persist-conventions-core — write one skill's section into a repo's
2
+ // CONTRIBUTING.md, point AGENTS.md at the file, and make CLAUDE.md a symlink to
3
+ // AGENTS.md (Claude Code reads CLAUDE.md, not AGENTS.md). Import-only: each skill's
4
+ // `persist-conventions.mjs` is the always-running CLI wrapper that names its
5
+ // section, so no main-module guard here.
6
+ //
7
+ // Byte-identical copies live in test-quality (Testing conventions), github-flow
8
+ // (CI conventions, Delivery) and data-catalog (Data catalog conventions);
9
+ // skills/conventions-sections.test.mjs keeps them identical and proves the sections
10
+ // coexist in one file.
11
+ //
12
+ // A section sits between `conventions:<id>` markers, so a re-run replaces only
13
+ // that block and keeps everything else, including other skills' sections.
14
+ // Nothing is written without --write: the user triggers the write, not an agent.
15
+
16
+ import fs from 'node:fs'
17
+ import path from 'node:path'
18
+
19
+ export const CONTRIBUTING_FILE = 'CONTRIBUTING.md'
20
+ const MENTIONS_CONTRIBUTING = /(?:^|[^\w-])CONTRIBUTING\.md/
21
+
22
+ export const AGENTS_SECTION = [
23
+ '## Contributing',
24
+ '',
25
+ `Follow [${CONTRIBUTING_FILE}](${CONTRIBUTING_FILE}) when writing, reviewing, or delivering code: tests, CI, data definitions, and what to do after each commit.`,
26
+ '',
27
+ ].join('\n')
28
+
29
+ export function markers(id) {
30
+ return [`<!-- conventions:${id}:start -->`, `<!-- conventions:${id}:end -->`]
31
+ }
32
+
33
+ export function sectionBlock({ id, owner, body }) {
34
+ const [start, end] = markers(id)
35
+ const note = `<!-- Written by the ${owner} skill: re-run its persist-conventions.mjs --write to update; edit outside these markers. -->`
36
+ return `${start}\n${note}\n\n${body.trim()}\n${end}\n`
37
+ }
38
+
39
+ // Pure: the new CONTRIBUTING.md text given the current one (or null).
40
+ export function renderConventions(current, id, block) {
41
+ if (current == null) return `# Contributing\n\n${block}`
42
+ const [start, end] = markers(id)
43
+ const from = current.indexOf(start)
44
+ const to = current.indexOf(end)
45
+ if (from !== -1 && to > from) {
46
+ const after = current.slice(to + end.length).replace(/^\r?\n/, '')
47
+ return current.slice(0, from) + block + after
48
+ }
49
+ return `${current.replace(/\s*$/, '')}\n\n${block}`
50
+ }
51
+
52
+ // Pure: the new AGENTS.md text given the current one (or null).
53
+ export function renderAgents(current) {
54
+ if (current == null) return `# AGENTS.md\n\n${AGENTS_SECTION}`
55
+ if (MENTIONS_CONTRIBUTING.test(current)) return current
56
+ return `${current.replace(/\s*$/, '')}\n\n${AGENTS_SECTION}`
57
+ }
58
+
59
+ // A missing CLAUDE.md becomes a symlink to AGENTS.md.
60
+ export const LINK_TO_AGENTS = Symbol('link CLAUDE.md to AGENTS.md')
61
+
62
+ // Pure: the new CLAUDE.md text given the current one (or null). A missing file
63
+ // becomes LINK_TO_AGENTS; a regular file keeps its content and gains the pointer
64
+ // unless it already names AGENTS.md or CONTRIBUTING.md.
65
+ export function renderClaude(current) {
66
+ if (current == null) return LINK_TO_AGENTS
67
+ if (/(?:^|[^\w-])(?:AGENTS|CONTRIBUTING)\.md/.test(current)) return current
68
+ return `${current.replace(/\s*$/, '')}\n\n${AGENTS_SECTION}`
69
+ }
70
+
71
+ export function persist(repoRoot, section, { write = false } = {}) {
72
+ const block = sectionBlock(section)
73
+ const plan = [
74
+ [CONTRIBUTING_FILE, (text) => renderConventions(text, section.id, block)],
75
+ ['AGENTS.md', renderAgents],
76
+ ['CLAUDE.md', renderClaude],
77
+ ]
78
+ return plan.map(([name, render]) => {
79
+ const file = path.join(repoRoot, name)
80
+ if (fs.lstatSync(file, { throwIfNoEntry: false })?.isSymbolicLink()) return { file: name, action: 'unchanged' }
81
+ const current = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : null
82
+ const next = render(current)
83
+ const action = current == null ? 'create' : next === current ? 'unchanged' : 'update'
84
+ if (next === LINK_TO_AGENTS) {
85
+ if (write) fs.symlinkSync('AGENTS.md', file)
86
+ return { file: name, action: 'link' }
87
+ }
88
+ if (write && action !== 'unchanged') fs.writeFileSync(file, next)
89
+ return { file: name, action }
90
+ })
91
+ }
92
+
93
+ // `section` = { id, owner, title, body }. Exit 0 on success, 2 on a usage error.
94
+ export function runCli(argv, section, { cwd = process.cwd(), log = console.log } = {}) {
95
+ let repoRoot = cwd
96
+ let write = false
97
+ for (let i = 0; i < argv.length; i++) {
98
+ if (argv[i] === '--write') write = true
99
+ else if (argv[i] === '--repo-root' && argv[i + 1]) repoRoot = path.resolve(cwd, argv[++i])
100
+ else {
101
+ log(`persist-conventions: unknown argument ${argv[i]}`)
102
+ return 2
103
+ }
104
+ }
105
+ if (!fs.statSync(repoRoot, { throwIfNoEntry: false })?.isDirectory()) {
106
+ log(`persist-conventions: not a directory: ${repoRoot}`)
107
+ return 2
108
+ }
109
+ const results = persist(repoRoot, section, { write })
110
+ const done = { create: 'created', link: 'linked to AGENTS.md', update: 'updated', unchanged: 'unchanged' }
111
+ for (const r of results) log(` ${r.file}: ${write || r.action === 'unchanged' ? done[r.action] : `would ${r.action}`}`)
112
+ const changed = results.filter((r) => r.action !== 'unchanged').length
113
+ log(write
114
+ ? `persist-conventions: ${section.title}: ${changed} file(s) written, ${results.length - changed} unchanged`
115
+ : `persist-conventions: ${section.title}: preview only, ${changed} file(s) would change; re-run with --write to write`)
116
+ return 0
117
+ }
@@ -0,0 +1,17 @@
1
+ // persist-conventions — the test principles as the `## Testing conventions`
2
+ // section of a repo's CONTRIBUTING.md (../SKILL.md, Persist mode). Run only when
3
+ // the user asks; previews unless --write.
4
+ //
5
+ // node persist-conventions.mjs [--repo-root <dir>] [--write]
6
+ import fs from 'node:fs'
7
+ import { fileURLToPath } from 'node:url'
8
+ import { runCli } from './persist-conventions-core.mjs'
9
+
10
+ const SECTION = {
11
+ id: 'testing',
12
+ owner: 'test-quality',
13
+ title: 'Testing conventions',
14
+ body: fs.readFileSync(fileURLToPath(new URL('../references/testing-conventions.md', import.meta.url)), 'utf8'),
15
+ }
16
+
17
+ process.exitCode = runCli(process.argv.slice(2), SECTION)
@@ -0,0 +1,104 @@
1
+ // Tests for persist-conventions: the real CLI against real files in a temp repo.
2
+ import { test } from 'node:test'
3
+ import assert from 'node:assert/strict'
4
+ import { spawnSync } from 'node:child_process'
5
+ import { existsSync, lstatSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
6
+ import { tmpdir } from 'node:os'
7
+ import { join } from 'node:path'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ import { markers } from './persist-conventions-core.mjs'
11
+
12
+ const CLI = fileURLToPath(new URL('./persist-conventions.mjs', import.meta.url))
13
+ const SKILL = readFileSync(fileURLToPath(new URL('../SKILL.md', import.meta.url)), 'utf8')
14
+ const TEMPLATE = readFileSync(fileURLToPath(new URL('../references/testing-conventions.md', import.meta.url)), 'utf8')
15
+ const [START, END] = markers('testing')
16
+
17
+ function withRepo(fn) {
18
+ const dir = mkdtempSync(join(tmpdir(), 'persist-conventions-'))
19
+ try {
20
+ return fn(dir, (name) => readFileSync(join(dir, name), 'utf8'))
21
+ } finally {
22
+ rmSync(dir, { recursive: true, force: true })
23
+ }
24
+ }
25
+
26
+ function run(dir, ...args) {
27
+ const res = spawnSync(process.execPath, [CLI, '--repo-root', dir, ...args], { encoding: 'utf8' })
28
+ return { code: res.status, out: res.stdout }
29
+ }
30
+
31
+ test('the persisted conventions carry one rule per SKILL.md principle, in order', () => {
32
+ const fromSkill = [...SKILL.matchAll(/^\| (\d) \| \[/gm)].map((m) => Number(m[1]))
33
+ const fromTemplate = [...TEMPLATE.matchAll(/^(\d+)\. /gm)].map((m) => Number(m[1]))
34
+ assert.ok(fromSkill.length >= 5, 'principle table not found in SKILL.md')
35
+ assert.deepEqual(fromTemplate, fromSkill)
36
+ })
37
+
38
+ test('without --write it previews and writes nothing', () => {
39
+ withRepo((dir) => {
40
+ const { code, out } = run(dir)
41
+ assert.equal(code, 0)
42
+ assert.match(out, /CONTRIBUTING\.md: would create/)
43
+ assert.match(out, /re-run with --write to write$/m)
44
+ assert.equal(existsSync(join(dir, 'CONTRIBUTING.md')), false)
45
+ assert.equal(existsSync(join(dir, 'AGENTS.md')), false)
46
+ })
47
+ })
48
+
49
+ test('--write creates CONTRIBUTING.md and AGENTS.md, links CLAUDE.md to it, and a re-run changes nothing', () => {
50
+ withRepo((dir, read) => {
51
+ const first = run(dir, '--write')
52
+ assert.equal(first.code, 0)
53
+ assert.match(first.out, /CONTRIBUTING\.md: created/)
54
+ assert.match(first.out, /AGENTS\.md: created/)
55
+ assert.match(first.out, /CLAUDE\.md: linked to AGENTS\.md/)
56
+ const conventions = read('CONTRIBUTING.md')
57
+ assert.ok(conventions.startsWith(`# Contributing\n\n${START}`))
58
+ assert.ok(conventions.includes('## Testing conventions'))
59
+ assert.ok(conventions.includes("6. Don't test config files"))
60
+ assert.match(read('AGENTS.md'), /\[CONTRIBUTING\.md\]\(CONTRIBUTING\.md\)/)
61
+
62
+ assert.ok(lstatSync(join(dir, 'CLAUDE.md')).isSymbolicLink())
63
+
64
+ const before = [conventions, read('AGENTS.md'), read('CLAUDE.md')]
65
+ assert.match(run(dir, '--write').out, /0 file\(s\) written, 3 unchanged$/m)
66
+ assert.deepEqual([read('CONTRIBUTING.md'), read('AGENTS.md'), read('CLAUDE.md')], before)
67
+ })
68
+ })
69
+
70
+ test('a stale section is replaced and the rest of each file is kept', () => {
71
+ withRepo((dir, read) => {
72
+ writeFileSync(join(dir, 'CONTRIBUTING.md'), `# Contributing\n\nUse tabs.\n\n${START}\nold principles\n${END}\n\n## Naming\n\ncamelCase.\n`)
73
+ writeFileSync(join(dir, 'AGENTS.md'), '# Agents\n\nRun `pnpm test`.\n')
74
+ run(dir, '--write')
75
+ const conventions = read('CONTRIBUTING.md')
76
+ assert.ok(conventions.startsWith('# Contributing\n\nUse tabs.\n\n'))
77
+ assert.ok(conventions.endsWith(`${END}\n\n## Naming\n\ncamelCase.\n`))
78
+ assert.ok(!conventions.includes('old principles'))
79
+ assert.equal(conventions.split(START).length, 2) // exactly one section
80
+ assert.ok(read('AGENTS.md').startsWith('# Agents\n\nRun `pnpm test`.\n\n## Contributing'))
81
+ })
82
+ })
83
+
84
+ test('an AGENTS.md that already names CONTRIBUTING.md is left alone; OLD_CONTRIBUTING.md is not a mention', () => {
85
+ withRepo((dir, read) => {
86
+ const agents = '# Agents\n\nSee CONTRIBUTING.md.\n'
87
+ writeFileSync(join(dir, 'AGENTS.md'), agents)
88
+ assert.match(run(dir, '--write').out, /AGENTS\.md: unchanged/)
89
+ assert.equal(read('AGENTS.md'), agents)
90
+ })
91
+ withRepo((dir, read) => {
92
+ writeFileSync(join(dir, 'AGENTS.md'), '# Agents\n\nSee OLD_CONTRIBUTING.md.\n')
93
+ assert.match(run(dir, '--write').out, /AGENTS\.md: updated/)
94
+ assert.match(read('AGENTS.md'), /\[CONTRIBUTING\.md\]\(CONTRIBUTING\.md\)/)
95
+ })
96
+ })
97
+
98
+ test('an unknown argument or a missing repo root is a usage error', () => {
99
+ withRepo((dir) => {
100
+ assert.equal(run(dir, '--force').code, 2)
101
+ assert.equal(run(join(dir, 'missing')).code, 2)
102
+ assert.equal(existsSync(join(dir, 'CONTRIBUTING.md')), false)
103
+ })
104
+ })
@@ -0,0 +1,3 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 1AboveIO