@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,201 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import fs from 'node:fs'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { spawnSync } from 'node:child_process'
6
+
7
+ // @characterizes mergify-audit-cli
8
+ // @covers mergify-audit-core
9
+ // @level integration
10
+ import { auditText, blockUnder, pullRequestBranches } from './audit-core.mjs'
11
+
12
+ const SCRIPT = fileURLToPath(new URL('./audit.mjs', import.meta.url))
13
+ const TEMPLATE = fileURLToPath(new URL('../assets/templates/mergify.yml', import.meta.url))
14
+ const status = (f, check) => f.find((x) => x.check === check)?.status
15
+ const run = (args) => spawnSync('node', [SCRIPT, ...args], { encoding: 'utf8' })
16
+ const tmp = (body) => { const p = `${fs.mkdtempSync('/tmp/mgaudit-')}/m.yml`; fs.writeFileSync(p, body); return p }
17
+
18
+ // ---- blockUnder: the one bit of structure-awareness ----
19
+ test('blockUnder returns the indented body of a key, and null when absent', () => {
20
+ const y = 'a:\n x: 1\n y: 2\nb:\n z: 3\n'
21
+ assert.match(blockUnder(y, 'a'), /x: 1/)
22
+ assert.doesNotMatch(blockUnder(y, 'a'), /z: 3/) // stops at the dedent to `b`
23
+ assert.equal(blockUnder(y, 'nope'), null)
24
+ })
25
+
26
+ // ---- the shipped template audits clean (dogfood: the default passes its own audit) ----
27
+ test('the skill template passes its own audit with no warn/fail', () => {
28
+ const f = auditText(fs.readFileSync(TEMPLATE, 'utf8'))
29
+ const bad = f.filter((x) => x.status === 'warn' || x.status === 'fail')
30
+ assert.deepEqual(bad, [], `template should be clean, got: ${JSON.stringify(bad)}`)
31
+ assert.equal(status(f, 'enqueue-policy'), 'pass')
32
+ })
33
+
34
+ // ---- decidable failures ----
35
+ test('deprecated auto_merge: true is a FAIL', () => {
36
+ assert.equal(status(auditText('merge_protections_settings:\n auto_merge: true\n'), 'deprecated-forms'), 'fail')
37
+ })
38
+ test('deprecated autoqueue is a FAIL', () => {
39
+ assert.equal(status(auditText('queue_rules:\n - name: d\n autoqueue: true\n'), 'deprecated-forms'), 'fail')
40
+ })
41
+ test('a comment that merely NAMES a deprecated form does not trip the check', () => {
42
+ assert.equal(status(auditText('# do not use auto_merge: true here\nqueue_rules: {}\n'), 'deprecated-forms'), 'pass')
43
+ })
44
+
45
+ // ---- enqueue policy ----
46
+ test('auto_merge_conditions without a review arm WARNs (the retired indiscriminate form)', () => {
47
+ assert.equal(status(auditText('merge_protections_settings:\n auto_merge_conditions:\n - "-draft"\n'), 'enqueue-policy'), 'warn')
48
+ })
49
+ test('auto_merge_conditions with approval but no changes-requested arm WARNs', () => {
50
+ const y = 'merge_protections_settings:\n auto_merge_conditions:\n - "#approved-reviews-by >= 1"\n'
51
+ assert.equal(status(auditText(y), 'enqueue-policy'), 'warn')
52
+ })
53
+ test('hybrid (approval + no open change request) PASSes', () => {
54
+ const y = 'merge_protections_settings:\n auto_merge_conditions:\n - "#approved-reviews-by >= 1"\n - "#changes-requested-reviews-by = 0"\n'
55
+ assert.equal(status(auditText(y), 'enqueue-policy'), 'pass')
56
+ })
57
+ test('no auto_merge_conditions is a NOTE (manual enqueue, ok if deliberate) — not a warn', () => {
58
+ assert.equal(status(auditText('merge_protections_settings:\n post_comment: true\n'), 'enqueue-policy'), 'note')
59
+ })
60
+
61
+ // ---- injection mode ----
62
+ test('missing branch_protection_injection_mode: merge WARNs when a queue exists', () => {
63
+ assert.equal(status(auditText('queue_rules:\n - name: d\n'), 'injection-mode'), 'warn')
64
+ })
65
+ test('no queue_rules → injection check ABSTAINs, never a false pass', () => {
66
+ assert.equal(status(auditText('merge_protections_settings: {}\n'), 'injection-mode'), 'abstain')
67
+ })
68
+
69
+ // ---- draft placement (epic-986) ----
70
+ test('-draft inside queue_conditions WARNs; in auto_merge_conditions it does NOT', () => {
71
+ const bad = 'queue_rules:\n - name: d\n queue_conditions:\n - -draft\n'
72
+ assert.equal(status(auditText(bad), 'draft-placement'), 'warn')
73
+ const ok = 'merge_protections_settings:\n auto_merge_conditions:\n - "-draft"\n - "#approved-reviews-by >= 1"\n'
74
+ assert.equal(status(auditText(ok), 'draft-placement'), 'pass')
75
+ })
76
+
77
+ // ---- gate anchor ----
78
+ test('a gate anchor asserted <2× WARNs; ≥2× PASSes', () => {
79
+ assert.equal(status(auditText('x: &gate {}\ny: *gate\n'), 'gate-anchor'), 'warn')
80
+ assert.equal(status(auditText('x: &gate {}\ny: *gate\nz: *gate\n'), 'gate-anchor'), 'pass')
81
+ })
82
+
83
+ // ---- batch mode (SKILL.md Rule 3) ----
84
+ test('no batch_size WARNs — unset runs at Mergify\'s built-in 1, so batches never form', () => {
85
+ assert.equal(status(auditText('queue_rules:\n - name: d\n queue_conditions:\n - base = main\n'), 'batch-mode'), 'warn')
86
+ })
87
+ test('explicit batch_size: 1 WARNs (batching off)', () => {
88
+ assert.equal(status(auditText('queue_rules:\n - name: d\n batch_size: 1\n'), 'batch-mode'), 'warn')
89
+ })
90
+ test('batch_size: 3 PASSes (batching on)', () => {
91
+ assert.equal(status(auditText('queue_rules:\n - name: d\n batch_size: 3\n'), 'batch-mode'), 'pass')
92
+ })
93
+ test('dynamic batch_size {min, max} PASSes (batching on)', () => {
94
+ assert.equal(status(auditText('queue_rules:\n - name: d\n batch_size:\n min: 1\n max: 10\n'), 'batch-mode'), 'pass')
95
+ })
96
+ test('no queue_rules → batch check ABSTAINs, never a false pass', () => {
97
+ assert.equal(status(auditText('merge_protections_settings: {}\n'), 'batch-mode'), 'abstain')
98
+ })
99
+
100
+ test('a queue rule with no checks_timeout WARNs: unset means auto, which dequeues green PRs', () => {
101
+ const f = auditText('queue_rules:\n - name: main\n batch_size: 3\n')
102
+ assert.equal(status(f, 'checks-timeout'), 'warn')
103
+ assert.match(f.find((x) => x.check === 'checks-timeout').detail, /main \(unset = auto\)/)
104
+ })
105
+ test('an explicit checks_timeout duration WARNs and names the rule', () => {
106
+ const f = auditText('queue_rules:\n - name: docs\n checks_timeout: null\n - name: main\n checks_timeout: 35 minutes\n')
107
+ assert.equal(status(f, 'checks-timeout'), 'warn')
108
+ const detail = f.find((x) => x.check === 'checks-timeout').detail
109
+ assert.match(detail, /main \(35 minutes\)/)
110
+ assert.doesNotMatch(detail, /docs/)
111
+ })
112
+ test('checks_timeout: null on every rule PASSes', () => {
113
+ const f = auditText('queue_rules:\n - name: docs\n checks_timeout: null\n - name: main\n batch_size: 3\n checks_timeout: null\n')
114
+ assert.equal(status(f, 'checks-timeout'), 'pass')
115
+ })
116
+ test('checks_timeout: null in defaults.queue_rule covers rules that do not override it', () => {
117
+ const base = 'defaults:\n queue_rule:\n checks_timeout: null\nqueue_rules:\n - name: main\n batch_size: 3\n'
118
+ assert.equal(status(auditText(base), 'checks-timeout'), 'pass')
119
+ assert.equal(status(auditText(base + ' - name: slow\n checks_timeout: 1 hour\n'), 'checks-timeout'), 'warn')
120
+ })
121
+ test('a comment that mentions checks_timeout: null does not count as setting it', () => {
122
+ const f = auditText('queue_rules:\n - name: main\n # checks_timeout: null\n batch_size: 3\n')
123
+ assert.equal(status(f, 'checks-timeout'), 'warn')
124
+ })
125
+ test('no queue_rules → checks-timeout ABSTAINs, never a false pass', () => {
126
+ assert.equal(status(auditText('merge_protections_settings: {}\n'), 'checks-timeout'), 'abstain')
127
+ })
128
+
129
+ test('absent batch_size WARN points at batch_size: 3 (the skill default)', () => {
130
+ const f = auditText('queue_rules:\n - name: d\n')
131
+ const d = f.find((x) => x.check === 'batch-mode').detail
132
+ assert.match(d, /batch_size: 3/)
133
+ })
134
+
135
+ // ---- CLI exit codes ----
136
+ // ---- stack-ready: commits kept, CI on stacked PRs (configuration.md, "Stack-ready") ----
137
+ test('a queue rule that squashes is a NOTE and names the rule; merge and merge-batch PASS', () => {
138
+ // kyc 2026-10-16: the default queue squashed, so a PR built on another conflicted after its parent landed.
139
+ // stack-sandbox 2026-10-20: a squash queue landed a GitHub-native stack, partial landing included, so it only matters off native stacks.
140
+ const cfg = (m) => `queue_rules:\n - name: release\n merge_method: merge\n - name: default\n merge_method: ${m}\n`
141
+ const squash = auditText(cfg('squash')).find((x) => x.check === 'merge-method')
142
+ assert.equal(squash.status, 'note')
143
+ assert.match(squash.detail, /default \(squash\) — fine for GitHub-native stacks; a Depends-On stack/)
144
+ assert.doesNotMatch(squash.detail, /release/)
145
+ assert.equal(status(auditText(cfg('merge-batch')), 'merge-method'), 'pass')
146
+ assert.equal(status(auditText(cfg("'squash'")), 'merge-method'), 'note', 'a quoted squash is still a squash')
147
+ assert.equal(status(auditText(cfg('somethingnew')), 'merge-method'), 'abstain', 'an unrecognized method is checked by hand, never passed')
148
+ assert.equal(status(auditText('a: 1\n'), 'merge-method'), 'abstain')
149
+ })
150
+
151
+ test('pullRequestBranches reads the base filter in every trigger shape, and null means any base', () => {
152
+ assert.deepEqual(pullRequestBranches('on:\n pull_request:\n branches: [main]\n paths-ignore:\n - docs/**\n'), ['main'], 'fmm-express test.yml')
153
+ assert.equal(pullRequestBranches('on:\n pull_request:\n branches: ["**"]\n schedule:\n - cron: "0 6 * * 1"\n'), null, 'a1 security-scan.yml')
154
+ assert.deepEqual(pullRequestBranches('on:\n pull_request:\n branches:\n - main\n - release/*\n'), ['main', 'release/*'])
155
+ assert.deepEqual(pullRequestBranches('on: { pull_request: { branches: [main] }, workflow_dispatch: }\n'), ['main'])
156
+ assert.equal(pullRequestBranches('on: { pull_request: , workflow_dispatch: }\n'), null)
157
+ assert.equal(pullRequestBranches('on:\n pull_request:\n workflow_dispatch:\n'), null)
158
+ assert.equal(pullRequestBranches('on:\n push:\n branches: [main]\n'), null, 'no pull_request trigger is not this check\'s business')
159
+ assert.equal(pullRequestBranches('on:\n pull_request_target:\n branches: [main]\n'), null)
160
+ assert.equal(pullRequestBranches('on:\n pull_request:\n # branches: [main]\n'), null, 'a commented-out filter is no filter')
161
+ // Round-5 audit: branches-ignore skips some base too, so a stack on that base gets no CI.
162
+ assert.deepEqual(pullRequestBranches('on:\n pull_request:\n branches-ignore: [rush/**]\n'), ['!rush/**'])
163
+ assert.deepEqual(pullRequestBranches('on:\n pull_request:\n branches-ignore:\n - \'stack/**\'\n'), ['!stack/**'])
164
+ })
165
+
166
+ test('stacked-pr-ci is a NOTE on base-filtered workflows, PASSes without filters, and ABSTAINs with none read', () => {
167
+ // fmm-express and identity 2026-10-16: required CI ran on PRs into main only, so Depends-On stacked PRs got none.
168
+ // stack-sandbox 2026-10-20: a [main]-filtered workflow ran on every PR of a GitHub-native stack.
169
+ const w = (name, text) => ({ name, text })
170
+ const filtered = auditText('a: 1\n', { workflows: [w('test.yml', 'on:\n pull_request:\n branches: [main]\n'), w('deploy.yml', 'on:\n push:\n branches: [main]\n')] }).find((x) => x.check === 'stacked-pr-ci')
171
+ assert.equal(filtered.status, 'note')
172
+ assert.match(filtered.detail, /test\.yml \[main\] — fine for GitHub-native stacks/)
173
+ assert.doesNotMatch(filtered.detail, /deploy\.yml/)
174
+ assert.equal(status(auditText('a: 1\n', { workflows: [w('ci.yml', 'on:\n pull_request:\n')] }), 'stacked-pr-ci'), 'pass')
175
+ assert.equal(status(auditText('a: 1\n', { workflows: [] }), 'stacked-pr-ci'), 'abstain')
176
+ assert.equal(status(auditText('a: 1\n'), 'stacked-pr-ci'), 'abstain')
177
+ })
178
+
179
+ test('CLI reads .github/workflows beside the config, or --workflows', () => {
180
+ const dir = fs.mkdtempSync('/tmp/mgaudit-')
181
+ fs.mkdirSync(`${dir}/.github/workflows`, { recursive: true })
182
+ fs.writeFileSync(`${dir}/.github/workflows/test.yml`, 'on:\n pull_request:\n branches: [main]\n')
183
+ fs.copyFileSync(TEMPLATE, `${dir}/.mergify.yml`)
184
+ const beside = run(['--file', `${dir}/.mergify.yml`, '--json'])
185
+ assert.equal(beside.status, 0, 'a base filter is a note: GitHub-native stacks still get CI')
186
+ assert.equal(JSON.parse(beside.stdout).findings.find((x) => x.check === 'stacked-pr-ci').status, 'note')
187
+ fs.mkdirSync(`${dir}/clean`)
188
+ fs.writeFileSync(`${dir}/clean/ci.yml`, 'on:\n pull_request:\n')
189
+ const clean = run(['--file', `${dir}/.mergify.yml`, '--workflows', `${dir}/clean`, '--json'])
190
+ assert.equal(clean.status, 0)
191
+ assert.equal(JSON.parse(clean.stdout).findings.find((x) => x.check === 'stacked-pr-ci').status, 'pass')
192
+ })
193
+
194
+ test('CLI exits 2 on FAIL, 1 on WARN, 0 with --allow-warn, 0 on PASS', () => {
195
+ assert.equal(run(['--file', tmp('merge_protections_settings:\n auto_merge: true\n')]).status, 2)
196
+ const warnCfg = tmp('queue_rules:\n - name: d\n')
197
+ assert.equal(run(['--file', warnCfg]).status, 1)
198
+ assert.equal(run(['--file', warnCfg, '--allow-warn']).status, 0)
199
+ assert.equal(run(['--file', TEMPLATE]).status, 0)
200
+ assert.equal(run(['--file', '/nonexistent.yml']).status, 2)
201
+ })
@@ -0,0 +1,106 @@
1
+ // @covers mergify-core-wrapper-topology
2
+ // @level integration
3
+ import { test } from 'node:test'
4
+ import assert from 'node:assert/strict'
5
+ import { spawnSync } from 'node:child_process'
6
+ import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync } from 'node:fs'
7
+ import { tmpdir } from 'node:os'
8
+ import { dirname, join } from 'node:path'
9
+ import { fileURLToPath, pathToFileURL } from 'node:url'
10
+
11
+ const SCRIPTS = dirname(fileURLToPath(import.meta.url))
12
+ const SKILL = dirname(SCRIPTS)
13
+ const TEMPLATE = join(SKILL, 'assets', 'templates', 'mergify.yml')
14
+ const AUDIT_CORE = join(SCRIPTS, 'audit-core.mjs')
15
+ const AUDIT_WRAPPER = join(SCRIPTS, 'audit.mjs')
16
+ const WATCH_CORE = join(SCRIPTS, 'watch-pr-delivery-core.mjs')
17
+ const WATCH_WRAPPER = join(SCRIPTS, 'watch-pr-delivery.mjs')
18
+ const STACK_CORE = join(SCRIPTS, 'stack-push-core.mjs')
19
+ const STACK_WRAPPER = join(SCRIPTS, 'stack-push.mjs')
20
+ const PRODUCTION_MODULES = [AUDIT_CORE, AUDIT_WRAPPER, WATCH_CORE, WATCH_WRAPPER, STACK_CORE, STACK_WRAPPER]
21
+
22
+ const runNode = (args) => spawnSync(process.execPath, args, { encoding: 'utf8' })
23
+
24
+ function importWrapper(wrapper, argv) {
25
+ const source = [
26
+ `process.argv = ['node', ${JSON.stringify(wrapper)}, ...${JSON.stringify(argv)}]`,
27
+ `const namespace = await import(${JSON.stringify(pathToFileURL(wrapper).href)})`,
28
+ "process.stderr.write(`WRAPPER_EXPORTS:${JSON.stringify(Object.keys(namespace))}`)",
29
+ ].join('\n')
30
+ return runNode(['--input-type=module', '--eval', source])
31
+ }
32
+
33
+ function assertSameRun(actual, expected, label) {
34
+ assert.equal(actual.status, expected.status, `${label}: exit status changed`)
35
+ assert.equal(actual.stdout, expected.stdout, `${label}: stdout changed`)
36
+ assert.equal(actual.stderr, expected.stderr, `${label}: stderr changed`)
37
+ }
38
+
39
+ test('importing either core is quiet and never launches a CLI', () => {
40
+ for (const core of [AUDIT_CORE, WATCH_CORE, STACK_CORE]) {
41
+ const result = runNode(['--input-type=module', '--eval', `await import(${JSON.stringify(pathToFileURL(core).href)})`])
42
+ assert.equal(result.status, 0, `${core}: ${result.stderr}`)
43
+ assert.equal(result.stdout, '', `${core} wrote CLI output during import`)
44
+ assert.equal(result.stderr, '', `${core} wrote CLI diagnostics during import`)
45
+ }
46
+ })
47
+
48
+ test('wrappers export nothing and invoke their core even when loaded through import()', () => {
49
+ const audit = importWrapper(AUDIT_WRAPPER, ['--file', TEMPLATE, '--json'])
50
+ assert.equal(audit.status, 0, audit.stderr)
51
+ assert.match(audit.stdout, /"verdict": "PASS"/)
52
+ assert.equal(audit.stderr, 'WRAPPER_EXPORTS:[]')
53
+
54
+ const watch = importWrapper(WATCH_WRAPPER, ['--help'])
55
+ assert.equal(watch.status, 0, watch.stderr)
56
+ assert.match(watch.stdout, /watch-pr-delivery --repo/)
57
+ assert.equal(watch.stderr, 'WRAPPER_EXPORTS:[]')
58
+
59
+ const stack = importWrapper(STACK_WRAPPER, ['--help'])
60
+ assert.equal(stack.status, 0, stack.stderr)
61
+ assert.match(stack.stdout, /stack-push --trunk/)
62
+ assert.equal(stack.stderr, 'WRAPPER_EXPORTS:[]')
63
+ })
64
+
65
+ test('direct, canonical-copy, and Claude-symlink wrapper launches preserve both CLI contracts', () => {
66
+ const home = mkdtempSync(join(tmpdir(), 'mergify-install-topology-'))
67
+ try {
68
+ const canonical = join(home, '.agents', 'skills', 'mergify')
69
+ const claude = join(home, '.claude', 'skills', 'mergify')
70
+ mkdirSync(dirname(canonical), { recursive: true })
71
+ mkdirSync(dirname(claude), { recursive: true })
72
+ cpSync(SKILL, canonical, { recursive: true })
73
+ symlinkSync(canonical, claude, 'dir')
74
+
75
+ const directAudit = runNode([AUDIT_WRAPPER, '--file', TEMPLATE, '--json'])
76
+ const directWatch = runNode([WATCH_WRAPPER, '--help'])
77
+ assert.equal(directAudit.status, 0, directAudit.stderr)
78
+ assert.equal(directWatch.status, 0, directWatch.stderr)
79
+
80
+ for (const [label, installedSkill] of [['canonical', canonical], ['claude-symlink', claude]]) {
81
+ assertSameRun(
82
+ runNode([join(installedSkill, 'scripts', 'audit.mjs'), '--file', TEMPLATE, '--json']),
83
+ directAudit,
84
+ `${label} audit`,
85
+ )
86
+ assertSameRun(
87
+ runNode([join(installedSkill, 'scripts', 'watch-pr-delivery.mjs'), '--help']),
88
+ directWatch,
89
+ `${label} watcher`,
90
+ )
91
+ }
92
+ } finally {
93
+ rmSync(home, { recursive: true, force: true })
94
+ }
95
+ })
96
+
97
+ test('Mergify production modules have no Engineering Workflow import or runtime dependency', () => {
98
+ for (const file of PRODUCTION_MODULES) {
99
+ const source = readFileSync(file, 'utf8')
100
+ assert.doesNotMatch(
101
+ source,
102
+ /engineering-runtime|engineering\/_lib|_lib\/main-module|isMainModule/,
103
+ `${file} reaches into Engineering Workflow`,
104
+ )
105
+ }
106
+ })
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "author": {
4
+ "login": "mergify"
5
+ },
6
+ "createdAt": "2026-07-28T10:31:42Z",
7
+ "body": "# Merge Protections\n\n🔴 **1 of 2 protections blocking** · waiting on 👀 reviews\n\n| | Protection | Waiting on |\n|:--:|:--|:--:|\n| 🔴 | **🚦 Auto-queue** | 👀 reviews |\n| 🟢 | skill-script-tests (or exempt) before merge | — |\n\n## 🔴 🚦 Auto-queue\n\n**Waiting for**\n\n- [ ] `#approved-reviews-by >= 1`\n\n<details><summary>This rule is failing.</summary>\n\nWhen all merge protections are satisfied and these conditions match, this pull request will be queued automatically.\n- [ ] `#approved-reviews-by >= 1`\n- [X] `#changes-requested-reviews-by = 0`\n- [X] `-draft`\n- [X] any of:\n - [X] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n\n</details>\n\n---\n\n<details><summary>Show 1 satisfied protection</summary>\n\n## 🟢 skill-script-tests (or exempt) before merge\n\nThe one CI gate, asserted as a required merge protection. Green when skill-script-tests succeeded, or when the PR touches no gated path (so the job was never created) — never absent, so the ruleset can require it without stranding a docs-only PR.\n- [X] any of:\n - [X] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n\n</details>"
8
+ },
9
+ {
10
+ "author": {
11
+ "login": "mergify"
12
+ },
13
+ "createdAt": "2026-07-28T11:02:07Z",
14
+ "body": "<!---\nDO NOT EDIT\n-*- Mergify Payload -*-\n{\"version\": 1, \"state\": \"dequeued\", \"queue_rule_name\": \"default\", \"queued_at\": \"2026-07-28T11:02:06.211243+00:00\", \"estimated_time_of_merge\": null, \"speculative_check_pr\": null, \"required_conditions\": []}\n-*- Mergify Payload End -*-\n-->\n\n# Merge Queue Status\n\n- ✅ **Entered queue** — `2026-07-28 11:02 UTC` · Rule: `default` · triggered by @exoulster with the [`@mergifyio queue` command](https://github.com/1aboveio/ai/pull/620#issuecomment-5103273321)\n- ❌ **Checks failed** · on draft #624\n- 🚫 **Left the queue** — `2026-07-28 11:04 UTC` · at `e6a855b3c80d22c47661b3a47cadba7ad58a862e`\n\nThis pull request spent **2 minutes 33 seconds** in the queue, including **1 minute 14 seconds** running CI.\n\n<details>\n<summary><strong>Waiting for</strong></summary>\n\n- [ ] any of:\n - [ ] `check-success = skill-script-tests`\n - [ ] `-files ~= ^skills/`\n- [ ] any of:\n - [ ] `check-success = skill-script-tests`\n - [ ] `-files ~= ^skills/`\n- [ ] any of:\n - [ ] `check-success = skill-script-tests-queue`\n - [ ] `-files ~= ^skills/`\n\n</details>\n<details>\n<summary>All conditions</summary>\n\n- [ ] all of [🛡 Merge Protections rule `skill-script-tests (or exempt) before merge`]:\n - [ ] any of:\n - [ ] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n- [ ] any of:\n - [ ] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n- [ ] any of:\n - [ ] `check-success = skill-script-tests-queue`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n\n</details>\n\n## Reason\n\nThe merge conditions cannot be satisfied due to failing checks\n\n- `skill-script-tests-queue`\n\nFailing checks:\n- 🟠 [skill-script-tests](https://github.com/1aboveio/ai/actions/runs/30353228583/job/90255382376) ([job log](https://github.com/1aboveio/ai/actions/runs/30353228583/job/90255382376))\n- ❌ [skill-script-tests-queue](https://github.com/1aboveio/ai/actions/runs/30353228583/job/90255382413) ([job log](https://github.com/1aboveio/ai/actions/runs/30353228583/job/90255382413))\n\n## Hint\n\nYou may have to fix your CI before adding the pull request to the queue again.\nIf you update this pull request, to fix the CI, it will automatically be requeued once the queue conditions match again.\nIf you think this was a flaky issue instead, you can requeue the pull request, without updating it, by posting a `@mergifyio queue` comment.\n\nRequeued — the merge queue status continues in [this comment ↓](https://github.com/1aboveio/ai/pull/620#issuecomment-5103476982)."
15
+ },
16
+ {
17
+ "author": {
18
+ "login": "mergify"
19
+ },
20
+ "createdAt": "2026-07-28T11:20:58Z",
21
+ "body": "<!---\nDO NOT EDIT\n-*- Mergify Payload -*-\n{\"version\": 1, \"state\": \"merged\", \"queue_rule_name\": \"default\", \"queued_at\": \"2026-07-28T11:20:56.782765+00:00\", \"estimated_time_of_merge\": null, \"speculative_check_pr\": null, \"required_conditions\": []}\n-*- Mergify Payload End -*-\n-->\n\n# Merge Queue Status\n\n- ✅ **Entered queue** — `2026-07-28 11:20 UTC` · Rule: `default` · triggered by @exoulster with the [`@mergifyio queue` command](https://github.com/1aboveio/ai/pull/620#issuecomment-5103472242)\n- ✅ **Checks passed** · on draft #627\n- ✅ **Merged** — `2026-07-28 11:25 UTC` · at `e6a855b3c80d22c47661b3a47cadba7ad58a862e` · merge\n\nThis pull request spent **4 minutes 29 seconds** in the queue, including **3 minutes 1 second** running CI.\n\n<details>\n<summary>Required conditions to merge</summary>\n\n- [X] all of [🛡 Merge Protections rule `skill-script-tests (or exempt) before merge`]:\n - [X] any of:\n - [X] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n- [X] any of:\n - [X] `check-success = skill-script-tests`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n- [X] any of:\n - [X] `check-success = skill-script-tests-queue`\n - [ ] all of:\n - [ ] `-files ~= ^skills/`\n - [X] `-files ~= ^\\.github/workflows/skill-gates\\.yml$`\n\n</details>"
22
+ },
23
+ {
24
+ "author": {
25
+ "login": "mergify"
26
+ },
27
+ "createdAt": "2026-07-28T11:21:32Z",
28
+ "body": "> queue\n\n#### ☑️ Command `queue` ignored because it is already running from a previous command.\n\n\n\n"
29
+ }
30
+ ]
@@ -0,0 +1,258 @@
1
+ // Import-only core for pushing a Mergify stack: one commit per PR, pushed with the flags every
2
+ // stack push needs, PR numbers reported, optionally enqueued together.
3
+ //
4
+ // node stack-push.mjs [--trunk origin/main] [--enqueue] [--draft] [--dry-run]
5
+ //
6
+ // Exit: 0 pushed (or planned), 2 usage, 3 not a stack repo, 4 fix the commits first,
7
+ // 5 push or enqueue failed, 6 mergify CLI older than MIN_CLI_VERSION.
8
+ import { execFileSync } from 'node:child_process'
9
+ import { existsSync } from 'node:fs'
10
+ import { isAbsolute, join } from 'node:path'
11
+
12
+ export const EXIT = { OK: 0, USAGE: 2, NOT_STACK_REPO: 3, FIX_COMMITS: 4, FAILED: 5, OLD_CLI: 6 }
13
+ // The oldest mergify CLI this skill supports: GitHub-native stacks by default (2026.9.16.1),
14
+ // called stable (2026.10.3), plus the retry and single-change fixes of 2026.10.4.
15
+ export const MIN_CLI_VERSION = '2026.10.5'
16
+ export const MISSING_CHANGE_ID_STATUS = 7
17
+ // `stack list` straight after a push can lag GitHub, and the push's own lines are not always
18
+ // readable (ai #1766, 2026-10-17: no PR read back, yet a list seconds later had it). Re-read
19
+ // the stack this many times, this far apart, before calling a commit PR-less.
20
+ export const REREAD_ATTEMPTS = 4
21
+ export const REREAD_DELAY_MS = 5_000
22
+ const sleepSync = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms)
23
+
24
+ const HELP = `stack-push --trunk origin/main [--enqueue] [--draft] [--dry-run]
25
+
26
+ Push the current branch's commits as a Mergify stack (one commit = one PR).
27
+ --trunk <remote/branch> stack base (default origin/main)
28
+ --enqueue post "@mergifyio queue" on every stack PR, in one pass
29
+ --draft open new PRs as drafts
30
+ --dry-run show the push plan; push nothing
31
+ Always keeps PR titles and bodies; never skips git hooks.
32
+ `
33
+
34
+ export function parseArgs(argv) {
35
+ const opts = { trunk: 'origin/main', enqueue: false, draft: false, dryRun: false, help: false }
36
+ for (let i = 0; i < argv.length; i++) {
37
+ const arg = argv[i]
38
+ if (arg === '--help' || arg === '-h') opts.help = true
39
+ else if (arg === '--enqueue') opts.enqueue = true
40
+ else if (arg === '--draft') opts.draft = true
41
+ else if (arg === '--dry-run') opts.dryRun = true
42
+ else if (arg === '--trunk') {
43
+ const value = argv[++i]
44
+ if (!value || !/^[^/\s]+\/\S+$/.test(value)) throw new Error('--trunk needs REMOTE/BRANCH, e.g. origin/main')
45
+ opts.trunk = value
46
+ } else throw new Error(`unknown option: ${arg}`)
47
+ }
48
+ if (opts.enqueue && opts.dryRun) throw new Error('--enqueue and --dry-run are mutually exclusive')
49
+ return opts
50
+ }
51
+
52
+ export function run(cmd, args) {
53
+ try {
54
+ const stdout = execFileSync(cmd, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 10 * 60_000 })
55
+ return { status: 0, stdout, stderr: '' }
56
+ } catch (error) {
57
+ return {
58
+ status: typeof error.status === 'number' ? error.status : 1,
59
+ stdout: String(error.stdout ?? ''),
60
+ stderr: String(error.stderr ?? error.message ?? ''),
61
+ }
62
+ }
63
+ }
64
+
65
+ // The hooks directory git actually uses: core.hooksPath when set, else <common git dir>/hooks.
66
+ export function hooksDir({ exec }) {
67
+ const configured = exec('git', ['config', '--get', 'core.hooksPath'])
68
+ const top = exec('git', ['rev-parse', '--show-toplevel'])
69
+ if (configured.status === 0 && configured.stdout.trim()) {
70
+ const path = configured.stdout.trim()
71
+ return isAbsolute(path) ? path : join(top.stdout.trim(), path)
72
+ }
73
+ const common = exec('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'])
74
+ if (common.status !== 0) return null
75
+ return join(common.stdout.trim(), 'hooks')
76
+ }
77
+
78
+ const versionParts = (text) => text.match(/\d+(?:\.\d+)+/)?.[0].split('.').map(Number) ?? null
79
+
80
+ // -1, 0 or 1 when the installed CLI is older, equal or newer than `min`; null when unreadable.
81
+ export function compareCliVersion(stdout, min = MIN_CLI_VERSION) {
82
+ const have = versionParts(stdout ?? ''), want = versionParts(min)
83
+ if (!have) return null
84
+ for (let i = 0; i < Math.max(have.length, want.length); i++) {
85
+ const d = (have[i] ?? 0) - (want[i] ?? 0)
86
+ if (d) return Math.sign(d)
87
+ }
88
+ return 0
89
+ }
90
+
91
+ export function missingChangeIdSha(stderr) {
92
+ const match = /Change-Id:`? line is missing on commit ([0-9a-f]{7,40})/.exec(stderr)
93
+ return match ? match[1] : null
94
+ }
95
+
96
+ export function readStack({ exec }, trunk) {
97
+ const listed = exec('mergify', ['stack', 'list', '--json', '--trunk', trunk])
98
+ if (listed.status === MISSING_CHANGE_ID_STATUS || missingChangeIdSha(listed.stderr)) {
99
+ return { error: 'missing-change-id', sha: missingChangeIdSha(listed.stderr), detail: listed.stderr.trim() }
100
+ }
101
+ if (listed.status !== 0) return { error: 'list-failed', detail: (listed.stderr || listed.stdout).trim() }
102
+ try {
103
+ const parsed = JSON.parse(listed.stdout)
104
+ return { entries: Array.isArray(parsed.entries) ? parsed.entries : [] }
105
+ } catch {
106
+ return { error: 'list-failed', detail: 'mergify stack list --json returned non-JSON output' }
107
+ }
108
+ }
109
+
110
+ export function pushArgs(opts) {
111
+ const args = ['stack', 'push', '--trunk', opts.trunk, '--keep-pull-request-title-and-body']
112
+ if (opts.draft) args.push('--draft')
113
+ if (opts.dryRun) args.push('--dry-run')
114
+ return args
115
+ }
116
+
117
+ // The PR each commit got, from `mergify stack push`'s own output, in stack order:
118
+ // ` · [created]<TAB><TAB>https://github.com/o/r/pull/1757<TAB>fix(mergify): …`
119
+ // ` ✓ [created]<TAB>af9adcc<TAB>https://github.com/o/r/pull/1839<TAB>fix(ci): …`
120
+ // The bullet and the commit column vary by push; match any bullet before the `[status]`.
121
+ // The push is the authority on what it just created. A `stack list` read straight after it can
122
+ // lag GitHub and report a fresh PR as missing (fmm-express #1816, ai #1756, 2026-10-16).
123
+ export function pushedPrs(stdout = '') {
124
+ const out = []
125
+ for (const line of stdout.split('\n')) {
126
+ const url = line.match(/https:\/\/github\.com\/[^\s]+\/pull\/(\d+)/)
127
+ if (!url || !/^\s*\S\s+\[[^\]]+\]/.test(line)) continue
128
+ const title = line.slice(line.indexOf(url[0]) + url[0].length).trim()
129
+ out.push({ title: title || null, url: url[0], pr: Number(url[1]) })
130
+ }
131
+ return out
132
+ }
133
+
134
+ const summarize = (entries) => entries.map((e) => ({
135
+ commit: e.commit_sha,
136
+ title: e.title,
137
+ pr: e.pull_number ?? null,
138
+ url: e.pull_url ?? null,
139
+ status: e.status ?? null,
140
+ }))
141
+
142
+ export function stackPush(argv, { exec = run, exists = existsSync, out = process.stdout, err = process.stderr, sleep = sleepSync } = {}) {
143
+ let opts
144
+ try {
145
+ opts = parseArgs(argv)
146
+ } catch (error) {
147
+ err.write(`stack-push: ${error.message}\n\n${HELP}`)
148
+ return EXIT.USAGE
149
+ }
150
+ if (opts.help) {
151
+ out.write(HELP)
152
+ return EXIT.OK
153
+ }
154
+
155
+ const hooks = hooksDir({ exec })
156
+ if (!hooks || !exists(join(hooks, 'mergify-hooks'))) {
157
+ err.write('stack-push: this repo has no Mergify stack hooks. Push with `git push` and open the PR with `gh pr create` (github-flow).\n')
158
+ return EXIT.NOT_STACK_REPO
159
+ }
160
+
161
+ const version = exec('mergify', ['--version'])
162
+ const order = version.status === 0 ? compareCliVersion(version.stdout) : null
163
+ if (order === null) {
164
+ err.write(`stack-push: could not read the mergify CLI version; this skill needs ${MIN_CLI_VERSION} or newer. Pushing anyway.\n`)
165
+ } else if (order < 0) {
166
+ err.write(`stack-push: mergify CLI ${version.stdout.trim().replace(/^mergify\s+/, '')} is older than ${MIN_CLI_VERSION}, the oldest this skill supports. Upgrade (\`brew upgrade mergify-cli\`; uv: \`uv tool upgrade mergify-cli\`), then rerun.\n`)
167
+ return EXIT.OLD_CLI
168
+ }
169
+
170
+ const before = readStack({ exec }, opts.trunk)
171
+ if (before.error === 'missing-change-id') {
172
+ err.write(`stack-push: commit ${before.sha ?? '(unknown)'} has no Change-Id. Tip commit: \`git commit --amend --no-edit\`. Older commit: \`mergify stack edit <sha>\`, \`git commit --amend --no-edit\`, \`git rebase --continue\`. Then rerun.\n`)
173
+ return EXIT.FIX_COMMITS
174
+ }
175
+ if (before.error) {
176
+ err.write(`stack-push: could not read the stack: ${before.detail}\n`)
177
+ return EXIT.FAILED
178
+ }
179
+ if (before.entries.length === 0) {
180
+ err.write(`stack-push: no commits on this branch above ${opts.trunk}. Commit first.\n`)
181
+ return EXIT.FIX_COMMITS
182
+ }
183
+
184
+ const pushed = exec('mergify', pushArgs(opts))
185
+ if (pushed.stdout) err.write(pushed.stdout)
186
+ if (pushed.status !== 0) {
187
+ const text = `${pushed.stderr}\n${pushed.stdout}`
188
+ if (/rebase failed|conflict/i.test(text)) {
189
+ err.write(`stack-push: rebase onto ${opts.trunk} hit a conflict. Resolve it, \`git rebase --continue\`, then rerun.\n`)
190
+ } else {
191
+ err.write(`stack-push: mergify stack push failed (exit ${pushed.status}): ${pushed.stderr.trim()}\n`)
192
+ }
193
+ return EXIT.FAILED
194
+ }
195
+ // The CLI falls back to a Depends-On stack where GitHub's stacking API is unavailable; that
196
+ // stack retargets only through head-branch deletion and needs the full Depends-On chain.
197
+ if (/not registered on GitHub/i.test(`${pushed.stdout}\n${pushed.stderr}`)) {
198
+ err.write('stack-push: not a GitHub-native stack: GitHub refused registration, so this is a Depends-On stack. Keep delete_branch_on_merge on (traps.md).\n')
199
+ }
200
+ if (opts.dryRun) {
201
+ out.write(`${JSON.stringify({ trunk: opts.trunk, dryRun: true, commits: summarize(before.entries) }, null, 2)}\n`)
202
+ return EXIT.OK
203
+ }
204
+
205
+ const reported = pushedPrs(pushed.stdout)
206
+ let prs
207
+ for (let attempt = 1; ; attempt++) {
208
+ const after = readStack({ exec }, opts.trunk)
209
+ if (after.error) {
210
+ err.write(`stack-push: pushed, but could not re-read the stack: ${after.detail}\n`)
211
+ return EXIT.FAILED
212
+ }
213
+ const listed = summarize(after.entries)
214
+ // Match by title, then by position when every commit got exactly one line.
215
+ const match = (p, i) => reported.find((x) => x.title && x.title === p.title)
216
+ ?? (reported.length === listed.length ? reported[i] : undefined)
217
+ prs = listed.map((p, i) => {
218
+ if (p.pr !== null) return p
219
+ const r = match(p, i)
220
+ return r ? { ...p, pr: r.pr, url: r.url, status: p.status === 'no_pr' ? 'open' : p.status } : p
221
+ })
222
+ if (attempt >= REREAD_ATTEMPTS || prs.every((p) => p.pr !== null)) break
223
+ sleep(REREAD_DELAY_MS)
224
+ }
225
+ const missing = prs.filter((p) => p.pr === null)
226
+ if (missing.length > 0) {
227
+ err.write(`stack-push: pushed, but ${missing.length} commit(s) have no PR: ${missing.map((p) => p.commit.slice(0, 12)).join(', ')}\n`)
228
+ return EXIT.FAILED
229
+ }
230
+
231
+ const enqueued = []
232
+ if (opts.enqueue) {
233
+ for (const p of prs) {
234
+ const commented = exec('gh', ['pr', 'comment', String(p.pr), '--body', '@mergifyio queue'])
235
+ if (commented.status !== 0) {
236
+ err.write(`stack-push: enqueue failed on #${p.pr}: ${commented.stderr.trim()}\n`)
237
+ out.write(`${JSON.stringify({ trunk: opts.trunk, prs, enqueued }, null, 2)}\n`)
238
+ return EXIT.FAILED
239
+ }
240
+ enqueued.push(p.pr)
241
+ }
242
+ }
243
+
244
+ // Mergify cancels a PR's queue request, queued or still waiting on checks, when new commits
245
+ // land on it (fmm-express #1846, 2026-10-17: a rebase push cancelled it and nothing said so).
246
+ const wasAt = new Map(before.entries.filter((e) => e.pull_number).map((e) => [e.pull_number, e.commit_sha]))
247
+ const moved = opts.enqueue ? [] : prs.filter((p) => wasAt.has(p.pr) && wasAt.get(p.pr) !== p.commit).map((p) => p.pr)
248
+ if (moved.length > 0) {
249
+ err.write(`stack-push: new commits on ${moved.map((n) => `#${n}`).join(' ')} cancel any Mergify queue request on them; requeue with --enqueue or \`@mergifyio queue\`\n`)
250
+ }
251
+ out.write(`${JSON.stringify({ trunk: opts.trunk, prs, enqueued }, null, 2)}\n`)
252
+ err.write(`stack-push: ${prs.length} PR(s): ${prs.map((p) => `#${p.pr}`).join(' ')}${opts.enqueue ? ' — all enqueued; watch each with watch-pr-delivery.mjs' : ''}\n`)
253
+ return EXIT.OK
254
+ }
255
+
256
+ export function runCli(argv) {
257
+ return stackPush(argv)
258
+ }
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './stack-push-core.mjs'
3
+
4
+ process.exitCode = runCli(process.argv.slice(2))