@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,398 @@
1
+ // head-check-set — the FULL observed state of one commit, not the named subset of it.
2
+ //
3
+ // A required-check plan answers "are the checks I named green?". #1081 is what that
4
+ // question cannot see. Two release workflows were rejected by GitHub at validation
5
+ // time; every push produced two runs that completed in the same second having executed
6
+ // ZERO jobs, named after the file path instead of the declared `name:`. That was
7
+ // visible for seven hours across fourteen commits, and the unit still earned an
8
+ // independent PASS and a merge-ready mark, because the one check anybody read
9
+ // (`skill-script-tests`) was green — and it genuinely was.
10
+ //
11
+ // THE SUBTLETY THAT DEFEATS THE OBVIOUS FIX. "Read every check-run instead of the
12
+ // named ones" would ALSO have missed #1081. A workflow GitHub cannot parse produces no
13
+ // check-run at all — not a red one, none. The real observation at that SHA:
14
+ //
15
+ // GET /commits/ee5dd91a…/check-runs → 4 entries, every one success/neutral/skipped
16
+ // GET /commits/ee5dd91a…/status → state "pending", zero statuses
17
+ // GET /actions/runs?head_sha=ee5dd91a… → 3 runs, TWO of them conclusion "failure"
18
+ // with name == path and zero jobs
19
+ //
20
+ // So the full state of a commit is the union of three channels — check-runs, legacy
21
+ // commit statuses, and Actions runs — and the third is the only one where a startup
22
+ // failure lives. This module classifies that union. Both halves are load-bearing: the
23
+ // union is what makes undeclared red visible, and the zero-job run is what makes the
24
+ // #1081 class NAMEABLE rather than a number in a count.
25
+ //
26
+ // WHAT THIS DELIBERATELY DOES NOT DO. It does not gate. Whether a red check nobody
27
+ // declared required should block a merge is a policy decision belonging to the human
28
+ // and to `.mergify.yml`, and a reporting script that quietly changed what merges would
29
+ // be a worse defect than the one it fixes. The partition names `undeclaredRed`
30
+ // separately from `requiredRed` precisely so a caller can act on the difference; the
31
+ // only outcome this module calls failing is the one the existing contract already
32
+ // blocks on — a REQUIRED check red or absent.
33
+
34
+ export const HEAD_CHECK_SET_VERSION = 1
35
+ export const HEAD_CHECK_SET_KIND = 'head-check-set'
36
+ export const OBSERVATION_SOURCES = Object.freeze(['check-run', 'commit-status', 'actions-run'])
37
+ export const OBSERVATION_STATES = Object.freeze(['green', 'red', 'neutral', 'pending'])
38
+
39
+ // Why `cancelled` counts as red: a cancelled required check is not a passed one, and
40
+ // the surrounding contract has said "skipped is never success" since epic-892. Neutral
41
+ // and skipped stay `neutral` — they are not passes either, but they are not evidence of
42
+ // breakage, and conflating the two is how a report gets ignored.
43
+ const RED_CONCLUSIONS = new Set(['failure', 'timed_out', 'action_required', 'startup_failure', 'stale', 'cancelled'])
44
+ const NEUTRAL_CONCLUSIONS = new Set(['skipped', 'neutral'])
45
+ const COMPLETED = new Set(['completed'])
46
+
47
+ // A run GitHub could not parse is reported with its file path where its name belongs,
48
+ // because there is no parsed `name:` to report. Corroborating, never sufficient: a
49
+ // workflow may legitimately declare no `name:`, in which case GitHub also uses the path.
50
+ const WORKFLOW_PATH = /^\.github\/workflows\/[^/]+\.ya?ml$/
51
+
52
+ const isObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
53
+ const nonEmpty = (value) => typeof value === 'string' && value.trim().length > 0
54
+ const SHA = /^[0-9a-f]{40}$/i
55
+ const lower = (value) => (value == null ? null : String(value).toLowerCase())
56
+
57
+ function stateOf(status, conclusion) {
58
+ const normalizedStatus = lower(status)
59
+ const normalizedConclusion = lower(conclusion)
60
+ if (normalizedStatus !== null && !COMPLETED.has(normalizedStatus)) return 'pending'
61
+ if (normalizedConclusion === null) return 'pending'
62
+ if (normalizedConclusion === 'success') return 'green'
63
+ if (NEUTRAL_CONCLUSIONS.has(normalizedConclusion)) return 'neutral'
64
+ if (RED_CONCLUSIONS.has(normalizedConclusion)) return 'red'
65
+ // Deny-by-default on a conclusion this module has never seen: an unknown conclusion
66
+ // read as green is exactly the failure this file exists to remove.
67
+ return 'red'
68
+ }
69
+
70
+ function commitStatusState(state) {
71
+ const normalized = lower(state)
72
+ if (normalized === 'success') return 'green'
73
+ if (normalized === 'pending') return 'pending'
74
+ return 'red'
75
+ }
76
+
77
+ /** Every check name the plan declares required, in any phase. */
78
+ export function requiredCheckNames(plan) {
79
+ const fromChecks = (plan?.checks || [])
80
+ .filter((check) => check?.admission === 'required' && nonEmpty(check?.name))
81
+ .map((check) => check.name)
82
+ const fromDiscovery = (plan?.discovery?.requiredChecks || []).filter(nonEmpty)
83
+ return [...new Set([...fromChecks, ...fromDiscovery])].sort()
84
+ }
85
+
86
+ function checkRunObservation(run) {
87
+ return {
88
+ source: 'check-run',
89
+ name: String(run?.name ?? ''),
90
+ state: stateOf(run?.status, run?.conclusion),
91
+ status: run?.status ?? null,
92
+ conclusion: run?.conclusion ?? null,
93
+ app: run?.app?.slug ?? null,
94
+ checkSuiteId: run?.check_suite?.id ?? null,
95
+ url: run?.html_url ?? null,
96
+ }
97
+ }
98
+
99
+ function commitStatusObservation(status) {
100
+ return {
101
+ source: 'commit-status',
102
+ name: String(status?.context ?? ''),
103
+ state: commitStatusState(status?.state),
104
+ status: 'completed',
105
+ conclusion: status?.state ?? null,
106
+ app: status?.creator?.login ?? null,
107
+ checkSuiteId: null,
108
+ url: status?.target_url ?? null,
109
+ }
110
+ }
111
+
112
+ /**
113
+ * An Actions run, plus the two facts that make #1081 nameable.
114
+ *
115
+ * `jobCount` is supplied by the caller because it costs one extra API call per run and
116
+ * this module is pure. A run that has completed with `jobCount === 0` executed nothing:
117
+ * that is the startup-failure signature, and it is the whole reason the Actions channel
118
+ * is read at all. `null` means the caller could not determine it — reported as unknown,
119
+ * never as zero, because "we did not look" and "there were none" must not render alike.
120
+ */
121
+ function actionsRunObservation(run) {
122
+ const name = String(run?.name ?? '')
123
+ const path = run?.path ?? null
124
+ const jobCount = Number.isInteger(run?.jobCount) ? run.jobCount : null
125
+ const state = stateOf(run?.status, run?.conclusion)
126
+ const completed = COMPLETED.has(lower(run?.status) ?? '')
127
+ return {
128
+ source: 'actions-run',
129
+ name,
130
+ state,
131
+ status: run?.status ?? null,
132
+ conclusion: run?.conclusion ?? null,
133
+ app: 'github-actions',
134
+ checkSuiteId: run?.check_suite_id ?? null,
135
+ url: run?.html_url ?? null,
136
+ runId: run?.id ?? null,
137
+ path,
138
+ event: run?.event ?? null,
139
+ jobCount,
140
+ // Recorded, never classified on. The obvious reading of "is this run attached to the
141
+ // pull request?" is the API's `pull_requests` array, and it is not usable: at
142
+ // ee5dd91a the perfectly healthy `pull_request`-event `Skill gates` run also carries
143
+ // `pull_requests: []`. Deriving an attachment boolean from it would report every
144
+ // healthy run as unattached. `event` is what actually distinguishes an out-of-band
145
+ // dispatch, and it is what `absenceReason` uses.
146
+ pullRequests: Array.isArray(run?.pull_requests) ? run.pull_requests.map((entry) => entry?.number ?? null) : [],
147
+ nameEqualsPath: nonEmpty(path) && name === path,
148
+ looksLikeWorkflowPath: WORKFLOW_PATH.test(name),
149
+ zeroJobs: completed && jobCount === 0,
150
+ }
151
+ }
152
+
153
+ /** Raw Actions runs (each optionally carrying an integer `jobCount`) as observations. */
154
+ export function observeActionsRuns(runs) {
155
+ return (Array.isArray(runs) ? runs : []).map(actionsRunObservation)
156
+ }
157
+
158
+ /**
159
+ * The #1081 signature: a run that COMPLETED, executed zero jobs, and did not succeed.
160
+ *
161
+ * Kept distinct from "a red run" on purpose. A red run with jobs failed while doing its
162
+ * work and its jobs say why; a red run with no jobs never started, and nothing else in
163
+ * the system says so — no check-run exists to be red. The name-equals-path corroboration
164
+ * is reported alongside rather than required, because a workflow with no declared `name:`
165
+ * produces the same coincidence honestly.
166
+ */
167
+ export function startupFailures(observations) {
168
+ return observations
169
+ .filter((entry) => entry.source === 'actions-run' && entry.zeroJobs && entry.state !== 'green')
170
+ .map((entry) => ({
171
+ runId: entry.runId,
172
+ name: entry.name,
173
+ path: entry.path,
174
+ event: entry.event,
175
+ conclusion: entry.conclusion,
176
+ state: entry.state,
177
+ nameEqualsPath: entry.nameEqualsPath,
178
+ looksLikeWorkflowPath: entry.looksLikeWorkflowPath,
179
+ url: entry.url,
180
+ }))
181
+ }
182
+
183
+ /**
184
+ * Why a required check produced no observation at all. This is #1058's distinction and
185
+ * it falls out of the same union: the three answers call for opposite responses, and the
186
+ * single string they share today ("no workflow run found") reads as *still queued* for
187
+ * all three.
188
+ */
189
+ export function ciAbsence(observations) {
190
+ const actionsRuns = (observations || []).filter((entry) => entry.source === 'actions-run')
191
+ return absenceReason(observations || [], actionsRuns)
192
+ }
193
+
194
+ function absenceReason(observations, actionsRuns) {
195
+ if (observations.some((entry) => entry.state === 'pending')) {
196
+ return {
197
+ reason: 'pending',
198
+ detail: 'a run for this SHA has not finished; waiting is correct and dispatching another would waste a run',
199
+ }
200
+ }
201
+ if (observations.length === 0) {
202
+ return {
203
+ reason: 'no-run-anywhere',
204
+ detail: 'no check-run, commit status or Actions run exists for this SHA — the triggering event was most likely never delivered; waiting is futile, a workflow_dispatch or a close/reopen at the same head is the intervention',
205
+ }
206
+ }
207
+ // #1058's third state: a run exists at this SHA, but it got there by hand. The check
208
+ // it produced is honest exact-head evidence and satisfies no merge-queue condition,
209
+ // and the situation is actionable NOW rather than something to wait out.
210
+ const dispatched = actionsRuns.filter((entry) => entry.event === 'workflow_dispatch')
211
+ if (dispatched.length && dispatched.length === actionsRuns.length) {
212
+ return {
213
+ reason: 'dispatched-out-of-band',
214
+ detail: `every Actions run at this SHA was started by workflow_dispatch (${dispatched.map((entry) => entry.runId).join(', ')}) — the event that would have created this check was never delivered; the dispatched run is honest exact-head evidence but satisfies no merge-queue check condition, so delivery still needs the event`,
215
+ }
216
+ }
217
+ return {
218
+ reason: 'absent-though-runs-completed',
219
+ detail: 'runs for this SHA have completed without ever producing this check — inspect the workflow trigger and path filters, and the startupFailures channel: a workflow GitHub refuses to parse creates a run and produces no check-run at all',
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Classify the full observed state of one head SHA.
225
+ *
226
+ * @param {object} input
227
+ * @param {string} input.repository owner/name
228
+ * @param {string} input.headSha the 40-character commit being described
229
+ * @param {object[]} [input.checkRuns] raw `GET /commits/{sha}/check-runs` entries
230
+ * @param {object[]} [input.statuses] raw `GET /commits/{sha}/status` `.statuses` entries
231
+ * @param {object[]} [input.actionsRuns] raw `GET /actions/runs?head_sha=` entries, each
232
+ * optionally carrying an integer `jobCount`
233
+ * @param {object|null} [input.plan] a required-check plan; OPTIONAL — with none, nothing
234
+ * is required and this degrades to a pure observation
235
+ * report rather than calling every red undeclared
236
+ * @param {string} [input.collectedAt]
237
+ */
238
+ export function classifyHeadCheckSet({
239
+ repository,
240
+ headSha,
241
+ checkRuns = [],
242
+ statuses = [],
243
+ actionsRuns = [],
244
+ plan = null,
245
+ collectedAt = new Date().toISOString(),
246
+ }) {
247
+ const observations = [
248
+ ...checkRuns.map(checkRunObservation),
249
+ ...statuses.map(commitStatusObservation),
250
+ ...actionsRuns.map(actionsRunObservation),
251
+ ]
252
+ const required = requiredCheckNames(plan)
253
+ const requiredSet = new Set(required)
254
+ for (const entry of observations) entry.required = requiredSet.has(entry.name)
255
+
256
+ const observedNames = new Set(observations.map((entry) => entry.name))
257
+ const actionsObservations = observations.filter((entry) => entry.source === 'actions-run')
258
+
259
+ const red = observations.filter((entry) => entry.state === 'red')
260
+ const partition = {
261
+ requiredRed: red.filter((entry) => entry.required),
262
+ // The #1081 case. Informational by contract — see this file's header — but never silent.
263
+ undeclaredRed: red.filter((entry) => !entry.required),
264
+ neverRan: required
265
+ .filter((name) => !observedNames.has(name))
266
+ .map((name) => ({ name, ...absenceReason(observations, actionsObservations) })),
267
+ pending: observations.filter((entry) => entry.state === 'pending'),
268
+ neutral: observations.filter((entry) => entry.state === 'neutral'),
269
+ green: observations.filter((entry) => entry.state === 'green'),
270
+ }
271
+ const signatures = { startupFailures: startupFailures(observations) }
272
+
273
+ // Outcome ordering is the caller's decision order, and `green-with-undeclared-red` is
274
+ // deliberately its own value rather than folded into either neighbour: it is the state
275
+ // #1081 was in for seven hours, and it must be neither "failure" (it does not block)
276
+ // nor "green" (it is not).
277
+ let outcome = 'green'
278
+ if (partition.requiredRed.length) outcome = 'required-red'
279
+ else if (partition.neverRan.length) outcome = 'required-missing'
280
+ else if (partition.pending.length) outcome = 'pending'
281
+ else if (partition.undeclaredRed.length || signatures.startupFailures.length) outcome = 'green-with-undeclared-red'
282
+
283
+ return {
284
+ version: HEAD_CHECK_SET_VERSION,
285
+ kind: HEAD_CHECK_SET_KIND,
286
+ repository,
287
+ headSha,
288
+ collectedAt,
289
+ planned: { required, planPresent: plan != null },
290
+ observations,
291
+ signatures,
292
+ partition,
293
+ summary: {
294
+ outcome,
295
+ counts: {
296
+ observations: observations.length,
297
+ checkRuns: checkRuns.length,
298
+ commitStatuses: statuses.length,
299
+ actionsRuns: actionsRuns.length,
300
+ requiredRed: partition.requiredRed.length,
301
+ undeclaredRed: partition.undeclaredRed.length,
302
+ neverRan: partition.neverRan.length,
303
+ pending: partition.pending.length,
304
+ startupFailures: signatures.startupFailures.length,
305
+ },
306
+ },
307
+ }
308
+ }
309
+
310
+ /**
311
+ * True when the REQUIRED set — and only the required set — is unsatisfied.
312
+ *
313
+ * This is the whole of the blocking judgement, isolated here so that the one place a
314
+ * caller could turn undeclared red into a merge decision is a single named function
315
+ * rather than an exit-code expression buried in a CLI.
316
+ */
317
+ export function blocksOnRequiredSet(artifact) {
318
+ return (artifact?.partition?.requiredRed?.length ?? 0) > 0
319
+ || (artifact?.partition?.neverRan?.length ?? 0) > 0
320
+ }
321
+
322
+ export function validateHeadCheckSetArtifact(artifact, { expectedHeadSha, label = 'headCheckSet' } = {}) {
323
+ const errors = []
324
+ if (!isObject(artifact)) return { ok: false, errors: [`${label} must be an object`] }
325
+ if (artifact.version !== HEAD_CHECK_SET_VERSION) errors.push(`${label}.version must be ${HEAD_CHECK_SET_VERSION}`)
326
+ if (artifact.kind !== HEAD_CHECK_SET_KIND) errors.push(`${label}.kind must be "${HEAD_CHECK_SET_KIND}"`)
327
+ if (!nonEmpty(artifact.repository) || !/^[^/\s]+\/[^/\s]+$/.test(artifact.repository)) errors.push(`${label}.repository must be owner/name`)
328
+ if (!nonEmpty(artifact.headSha) || !SHA.test(artifact.headSha)) errors.push(`${label}.headSha must be a full 40-character commit SHA`)
329
+ else if (expectedHeadSha && artifact.headSha !== expectedHeadSha) errors.push(`${label} is STALE: stamped ${artifact.headSha}, expected ${expectedHeadSha}`)
330
+ if (!Array.isArray(artifact.observations)) errors.push(`${label}.observations must be an array`)
331
+ else {
332
+ for (const [index, entry] of artifact.observations.entries()) {
333
+ const at = `${label}.observations[${index}]`
334
+ if (!isObject(entry)) { errors.push(`${at} must be an object`); continue }
335
+ if (!OBSERVATION_SOURCES.includes(entry.source)) errors.push(`${at}.source must be ${OBSERVATION_SOURCES.join('|')}`)
336
+ if (!nonEmpty(entry.name)) errors.push(`${at}.name must be a non-empty string`)
337
+ if (!OBSERVATION_STATES.includes(entry.state)) errors.push(`${at}.state must be ${OBSERVATION_STATES.join('|')}`)
338
+ if (typeof entry.required !== 'boolean') errors.push(`${at}.required must be boolean`)
339
+ }
340
+ }
341
+ if (!isObject(artifact.partition)) errors.push(`${label}.partition must be an object`)
342
+ else {
343
+ for (const key of ['requiredRed', 'undeclaredRed', 'neverRan', 'pending', 'neutral', 'green']) {
344
+ if (!Array.isArray(artifact.partition[key])) errors.push(`${label}.partition.${key} must be an array`)
345
+ }
346
+ for (const [index, entry] of (artifact.partition.neverRan || []).entries()) {
347
+ const at = `${label}.partition.neverRan[${index}]`
348
+ if (!isObject(entry) || !nonEmpty(entry.name)) errors.push(`${at}.name must be a non-empty string`)
349
+ // The reason is the entire point of the row: an absence without one reads as
350
+ // "still queued" for all three of #1058's cases.
351
+ else if (!nonEmpty(entry.reason) || !nonEmpty(entry.detail)) errors.push(`${at} requires an actionable reason and detail`)
352
+ }
353
+ }
354
+ if (!isObject(artifact.signatures) || !Array.isArray(artifact.signatures.startupFailures)) errors.push(`${label}.signatures.startupFailures must be an array`)
355
+ if (!isObject(artifact.summary) || !nonEmpty(artifact.summary.outcome)) errors.push(`${label}.summary.outcome must be a non-empty string`)
356
+ return { ok: errors.length === 0, errors }
357
+ }
358
+
359
+ function describe(entry) {
360
+ const detail = entry.source === 'actions-run'
361
+ ? ` — run ${entry.runId ?? '?'}, event ${entry.event ?? '?'}, ${entry.jobCount === null ? 'job count unknown' : `${entry.jobCount} job(s)`}`
362
+ : ''
363
+ return `${entry.name} [${entry.source}] ${entry.conclusion ?? entry.status ?? 'pending'}${detail}`
364
+ }
365
+
366
+ export function renderHeadCheckSet(artifact) {
367
+ const lines = [
368
+ '<!-- generated by head-check-set.mjs — do not hand-edit; re-run collect -->',
369
+ `**Full check set at \`${artifact.headSha}\`** (${artifact.repository}, collected ${artifact.collectedAt})`,
370
+ '',
371
+ `- Outcome: **${artifact.summary?.outcome}** — ${artifact.summary?.counts?.observations ?? 0} observation(s) across `
372
+ + `${artifact.summary?.counts?.checkRuns ?? 0} check-run(s), ${artifact.summary?.counts?.commitStatuses ?? 0} commit status(es), `
373
+ + `${artifact.summary?.counts?.actionsRuns ?? 0} Actions run(s)`,
374
+ `- Required by the plan: ${artifact.planned?.planPresent ? (artifact.planned.required.join(', ') || 'none') : 'NO PLAN SUPPLIED — nothing is classified required, so this is an observation report only'}`,
375
+ ]
376
+ const section = (title, rows) => {
377
+ if (!rows.length) return
378
+ lines.push(`- ${title}:`)
379
+ for (const row of rows) lines.push(` - ${row}`)
380
+ }
381
+ section('REQUIRED and red (blocking under the existing contract)', artifact.partition?.requiredRed?.map(describe) ?? [])
382
+ section(
383
+ 'NOT required and red (informational — surfaced, never gated here; whether it should block belongs to `.mergify.yml` and the human)',
384
+ artifact.partition?.undeclaredRed?.map(describe) ?? [],
385
+ )
386
+ section(
387
+ 'Required but never ran at all',
388
+ artifact.partition?.neverRan?.map((row) => `${row.name}: ${row.reason} — ${row.detail}`) ?? [],
389
+ )
390
+ section(
391
+ 'Workflow runs that completed having executed ZERO jobs (the #1081 startup-failure signature)',
392
+ artifact.signatures?.startupFailures?.map((row) =>
393
+ `run ${row.runId} \`${row.name}\` (${row.conclusion}) executed no jobs`
394
+ + `${row.nameEqualsPath ? ' and its name equals its file path — corroborating a workflow GitHub refused to parse' : ''}`) ?? [],
395
+ )
396
+ section('Pending', artifact.partition?.pending?.map(describe) ?? [])
397
+ return lines.join('\n')
398
+ }
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+
7
+ import { isMainModule } from './main-module.mjs';
8
+
9
+ export const MANUAL_ONLY = 'manual-only';
10
+ const SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
11
+
12
+ function frontmatterBounds(contents) {
13
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(contents);
14
+ if (!match) throw new Error('SKILL.md must begin with YAML frontmatter');
15
+ return { body: match[1], end: match[0].length };
16
+ }
17
+
18
+ function manualOnlySkill(contents) {
19
+ const frontmatter = frontmatterBounds(contents);
20
+ const declarations = frontmatter.body.match(/^disable-model-invocation\s*:\s*.*$/gm) ?? [];
21
+ if (declarations.length > 1) throw new Error('SKILL.md repeats disable-model-invocation');
22
+
23
+ const body = declarations.length === 1
24
+ ? frontmatter.body.replace(/^disable-model-invocation\s*:\s*.*$/m, 'disable-model-invocation: true')
25
+ : `${frontmatter.body}\ndisable-model-invocation: true`;
26
+ return `---\n${body}\n---\n${contents.slice(frontmatter.end)}`;
27
+ }
28
+
29
+ function manualOnlyOpenAi(contents) {
30
+ const policyHeaders = contents.match(/^policy\s*:\s*$/gm) ?? [];
31
+ if (policyHeaders.length > 1) throw new Error('agents/openai.yaml repeats policy');
32
+ if (policyHeaders.length === 0) {
33
+ const prefix = contents.length === 0 || contents.endsWith('\n') ? contents : `${contents}\n`;
34
+ return `${prefix}policy:\n allow_implicit_invocation: false\n`;
35
+ }
36
+
37
+ const lines = contents.split('\n');
38
+ const policyIndex = lines.findIndex((line) => /^policy\s*:\s*$/.test(line));
39
+ let policyEnd = lines.length;
40
+ for (let index = policyIndex + 1; index < lines.length; index += 1) {
41
+ if (/^[^\s#][^:]*\s*:/.test(lines[index])) {
42
+ policyEnd = index;
43
+ break;
44
+ }
45
+ }
46
+ const declarations = lines
47
+ .slice(policyIndex + 1, policyEnd)
48
+ .filter((line) => /^\s+allow_implicit_invocation\s*:/.test(line));
49
+ if (declarations.length > 1) throw new Error('agents/openai.yaml repeats policy.allow_implicit_invocation');
50
+ if (declarations.length === 1) {
51
+ return lines.map((line, index) => (
52
+ index > policyIndex && index < policyEnd && /^\s+allow_implicit_invocation\s*:/.test(line)
53
+ ? ' allow_implicit_invocation: false'
54
+ : line
55
+ )).join('\n');
56
+ }
57
+ lines.splice(policyIndex + 1, 0, ' allow_implicit_invocation: false');
58
+ return lines.join('\n');
59
+ }
60
+
61
+ export function manualOnlyPolicyFindings(skillDirectory) {
62
+ const findings = [];
63
+ const skillPath = join(skillDirectory, 'SKILL.md');
64
+ const openaiPath = join(skillDirectory, 'agents', 'openai.yaml');
65
+ if (!existsSync(skillPath)) return ['SKILL.md is missing'];
66
+ const skill = readFileSync(skillPath, 'utf8');
67
+ const declarations = frontmatterBounds(skill).body.match(/^disable-model-invocation\s*:\s*true\s*$/gm) ?? [];
68
+ if (declarations.length !== 1) findings.push('SKILL.md must declare disable-model-invocation: true exactly once');
69
+ if (!existsSync(openaiPath)) {
70
+ findings.push('agents/openai.yaml is missing');
71
+ } else {
72
+ const openai = readFileSync(openaiPath, 'utf8');
73
+ const policies = openai.match(/^policy\s*:\s*$/gm) ?? [];
74
+ const implicit = openai.match(/^\s+allow_implicit_invocation\s*:\s*false\s*$/gm) ?? [];
75
+ if (policies.length !== 1 || implicit.length !== 1) {
76
+ findings.push('agents/openai.yaml must declare policy.allow_implicit_invocation: false exactly once');
77
+ }
78
+ }
79
+ return findings;
80
+ }
81
+
82
+ // Restore the reviewed upstream bytes for source-integrity hashing. The installed tree must first
83
+ // pass manualOnlyPolicyFindings; these exact trailing additions are the only intentional divergence.
84
+ export function reviewedSourceInjections(skillDirectory, policy) {
85
+ if (policy !== MANUAL_ONLY) return [];
86
+ const findings = manualOnlyPolicyFindings(skillDirectory);
87
+ if (findings.length > 0) throw new Error(findings.join('; '));
88
+ const skill = readFileSync(join(skillDirectory, 'SKILL.md'), 'utf8')
89
+ .replace(/^disable-model-invocation: true\n/m, '');
90
+ const openai = readFileSync(join(skillDirectory, 'agents', 'openai.yaml'), 'utf8')
91
+ .replace(/policy:\n allow_implicit_invocation: false\n?$/, '');
92
+ return [
93
+ { relativePath: 'SKILL.md', contents: skill },
94
+ { relativePath: 'agents/openai.yaml', contents: openai },
95
+ ];
96
+ }
97
+
98
+ export function clearInvocationPolicy({ installName, policy, skillsRoot = join(homedir(), '.agents', 'skills') }) {
99
+ if (!SKILL_NAME.test(installName ?? '')) throw new Error(`invalid installed skill name ${JSON.stringify(installName)}`);
100
+ if (policy !== MANUAL_ONLY) throw new Error(`unsupported invocation policy ${JSON.stringify(policy)}`);
101
+ const skillDirectory = join(skillsRoot, installName);
102
+ const skillPath = join(skillDirectory, 'SKILL.md');
103
+ const openaiPath = join(skillDirectory, 'agents', 'openai.yaml');
104
+ if (!existsSync(skillPath) || !existsSync(openaiPath)) throw new Error(`installed skill is incomplete: ${skillDirectory}`);
105
+ const skill = readFileSync(skillPath, 'utf8');
106
+ const openai = readFileSync(openaiPath, 'utf8');
107
+ const hasSkillPolicy = /^disable-model-invocation\s*:/m.test(frontmatterBounds(skill).body);
108
+ const hasOpenAiPolicy = /^policy\s*:\s*$/m.test(openai) || /^\s+allow_implicit_invocation\s*:/m.test(openai);
109
+ if (!hasSkillPolicy && !hasOpenAiPolicy) {
110
+ return { installName, policy: 'implicit', skillDirectory, changed: false };
111
+ }
112
+ const injected = Object.fromEntries(reviewedSourceInjections(skillDirectory, policy)
113
+ .map((entry) => [entry.relativePath, entry.contents]));
114
+ writeFileSync(skillPath, injected['SKILL.md']);
115
+ writeFileSync(openaiPath, injected['agents/openai.yaml']);
116
+ return { installName, policy: 'implicit', skillDirectory, changed: true };
117
+ }
118
+
119
+ export function applyInvocationPolicy({ installName, policy, skillsRoot = join(homedir(), '.agents', 'skills') }) {
120
+ if (!SKILL_NAME.test(installName ?? '')) throw new Error(`invalid installed skill name ${JSON.stringify(installName)}`);
121
+ if (policy !== MANUAL_ONLY) throw new Error(`unsupported invocation policy ${JSON.stringify(policy)}`);
122
+ const skillDirectory = join(skillsRoot, installName);
123
+ const skillPath = join(skillDirectory, 'SKILL.md');
124
+ if (!existsSync(skillPath)) throw new Error(`installed skill is missing: ${skillPath}`);
125
+ const openaiPath = join(skillDirectory, 'agents', 'openai.yaml');
126
+
127
+ const skillBefore = readFileSync(skillPath, 'utf8');
128
+ const skillAfter = manualOnlySkill(skillBefore);
129
+ if (skillAfter !== skillBefore) writeFileSync(skillPath, skillAfter);
130
+
131
+ mkdirSync(dirname(openaiPath), { recursive: true });
132
+ const openaiBefore = existsSync(openaiPath) ? readFileSync(openaiPath, 'utf8') : '';
133
+ const openaiAfter = manualOnlyOpenAi(openaiBefore);
134
+ if (openaiAfter !== openaiBefore) writeFileSync(openaiPath, openaiAfter);
135
+
136
+ const findings = manualOnlyPolicyFindings(skillDirectory);
137
+ if (findings.length > 0) throw new Error(findings.join('; '));
138
+ return { installName, policy, skillDirectory, changed: skillAfter !== skillBefore || openaiAfter !== openaiBefore };
139
+ }
140
+
141
+ function selectionEnablesTdd(env = process.env) {
142
+ const stateHome = env.XDG_STATE_HOME || join(env.HOME || homedir(), '.local', 'state');
143
+ const path = join(stateHome, '1aboveio-skills', 'selection.json');
144
+ if (!existsSync(path)) return true;
145
+ try {
146
+ const state = JSON.parse(readFileSync(path, 'utf8'));
147
+ if (state.tddImplicitInvocation === undefined) return true;
148
+ if (typeof state.tddImplicitInvocation !== 'boolean') {
149
+ throw new Error('tddImplicitInvocation must be a boolean');
150
+ }
151
+ return state.tddImplicitInvocation;
152
+ } catch (error) {
153
+ throw new Error(`cannot read TDD invocation selection at ${path}: ${error.message}`);
154
+ }
155
+ }
156
+
157
+ export function reconcileInvocationPolicy(options) {
158
+ return selectionEnablesTdd(options.env)
159
+ ? clearInvocationPolicy(options)
160
+ : applyInvocationPolicy(options);
161
+ }
162
+
163
+ function parseArgs(argv) {
164
+ const parsed = { installName: null, policy: null, skillsRoot: undefined, fromSelection: false };
165
+ for (let index = 0; index < argv.length; index += 1) {
166
+ const arg = argv[index];
167
+ if (arg === '--skill') parsed.installName = argv[++index];
168
+ else if (arg === '--policy') parsed.policy = argv[++index];
169
+ else if (arg === '--skills-root') parsed.skillsRoot = argv[++index];
170
+ else if (arg === '--from-selection') parsed.fromSelection = true;
171
+ else throw new Error(`unknown argument ${arg}`);
172
+ }
173
+ return parsed;
174
+ }
175
+
176
+ if (isMainModule(import.meta.url)) {
177
+ try {
178
+ const parsed = parseArgs(process.argv.slice(2));
179
+ const result = parsed.fromSelection
180
+ ? reconcileInvocationPolicy(parsed)
181
+ : applyInvocationPolicy(parsed);
182
+ process.stdout.write(`${JSON.stringify(result)}\n`);
183
+ } catch (error) {
184
+ process.stderr.write(`invocation-policy: ${error.message}\n`);
185
+ process.exitCode = 1;
186
+ }
187
+ }