@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,151 @@
1
+ # The result
2
+
3
+ How to rate findings and, when a caller gives a result path, the file to write. Without a caller,
4
+ report in chat as [SKILL.md](../SKILL.md#5-run-the-checks-and-report-2-min) says.
5
+
6
+ ## Severity
7
+
8
+ Only P0/P1 block. Pick the level by consequence, not by which pass found it. Never report P3.
9
+
10
+ | Level | Meaning |
11
+ |---|---|
12
+ | **P0** | Exploitable security, auth, tenancy, money, or data-loss defect on a reachable path. |
13
+ | **P1** | A contract break: an acceptance criterion unmet or wrong, required behavior wrong, a correctness bug with a concrete breaking input, a required repo standard or gate violated, a dishonest test cited as proof, or prose agents act on that contradicts the code. |
14
+ | **P2** | A real defect outside the contract: optional hardening, an untested branch whose failure is observable, scope creep, test tooling that hides no product bug. |
15
+ | **P3** | Not reported. Cleanup, naming, smells, cosmetics, architecture opinions, minor pre-existing issues: leave them out of the result and the chat report. |
16
+
17
+ A pre-existing defect the diff neither causes nor worsens is never P0/P1 for this change, however
18
+ serious; rate it P2 when serious (leave it out otherwise) and say in its summary how serious it is, so
19
+ its follow-up gets triaged.
20
+
21
+ ## The result file
22
+
23
+ Write it to the path the caller gave. Callers decide the next step from severities alone, so do
24
+ not state a verdict. The file is incomplete when `complete` is not `true`, `commands` is empty (a
25
+ skip record excepted), `head` is not the HEAD you reviewed, an `executionIncident` is open, or a
26
+ P2 lacks its follow-up URL when the caller asked for follow-ups.
27
+
28
+ ```json
29
+ {
30
+ "version": 1, "unit": "1201", "round": 1, "fixRound": 1, "head": "<reviewed sha>",
31
+ "complete": true, "executionIncident": null,
32
+ "mergeBase": "<merge-base sha from pr-context>", "patchId": "<patchId from pr-context>",
33
+ "patchFingerprint": "<patchFingerprint from pr-context>",
34
+ "tier": "full", "fixLinesSinceFull": 0, "oversize": false,
35
+ "commands": ["npm test -- src/billing", "npm run lint"],
36
+ "notRun": [{ "command": "npm run e2e:android", "error": "no emulator in this environment" }],
37
+ "passes": {
38
+ "spec": "done", "correctness": "done", "tests": "done", "standards": "done"
39
+ },
40
+ "sweeps": [
41
+ {
42
+ "rule": "every refund row carries currency, rate, and amount, or none of them",
43
+ "points": [
44
+ { "location": "src/billing/refund.ts:30", "enforced": true },
45
+ { "location": "src/export/refunds.ts:12", "enforced": false, "finding": "R1" }
46
+ ]
47
+ }
48
+ ],
49
+ "windows": [
50
+ { "step": "SessionStore.logout", "location": "src/export/temp-file.ts:20",
51
+ "callers": ["settings button", "401 handler", "session-expiry timer"],
52
+ "coincides": ["app backgrounded", "offline"],
53
+ "outcomes": { "success": "file deleted", "error": "file kept (R4)", "timeout": "file kept (R4)" },
54
+ "outcome": "backgrounded: temp file kept until logout settles (R4)" }
55
+ ],
56
+ "boundaries": [
57
+ { "location": "src/billing/parse.ts:8", "pattern": "/^\\d+(\\.\\d{2})?$/",
58
+ "inputs": ["\"\"", "\"1.\"", "\"1.234\"", "\" 1.00\"", "\"-1.00\""], "outcome": "all rejected" }
59
+ ],
60
+ "findings": [
61
+ {
62
+ "id": "R1", "severity": "P1", "pass": "correctness",
63
+ "summary": "Refund path converts USD→EUR with the inverted rate",
64
+ "file": "src/billing/refund.ts", "line": 42,
65
+ "trigger": "refund 100 USD at rate 0.9 returns 111.11 EUR, expected 90.00",
66
+ "rule": "every currency conversion multiplies by the source-to-target rate",
67
+ "paths": [
68
+ { "path": "src/billing/refund.ts:42", "status": "open", "evidence": "divides by rate" },
69
+ { "path": "src/billing/charge.ts:31", "status": "closed", "evidence": "convert() at :31" }
70
+ ]
71
+ },
72
+ {
73
+ "id": "R2", "severity": "P2", "pass": "tests",
74
+ "summary": "refund rounding branch for zero-decimal currencies has no test",
75
+ "file": "src/billing/refund.ts", "line": 58,
76
+ "followUpUrl": "https://github.com/o/r/issues/9"
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ - `unit` is the caller's id for the change, when it gave one.
83
+ - `complete` is `true` only when every pass finished. Stopped part-way (interrupted, out of
84
+ context, or told to stop; a slow pass is not a reason): set it to `false`, set each pass you did
85
+ not finish to `unfinished`, keep every command you ran and every finding you wrote, and stop;
86
+ the caller resumes you or replaces the round. Never erase checks or invent findings to make it
87
+ look done.
88
+ - `notRun` lists each check the environment cannot run at all (no emulator, no device, no
89
+ credentials for a live service), with the command and its error verbatim; `[]` when none. It is
90
+ not a finding and does not make the review incomplete. A criterion whose proving test exists
91
+ but is listed here is not "unverified": say so in its spec row.
92
+ - `executionIncident` is for something that broke during this review and can be fixed (the test
93
+ database crashed, the runner lost its network): `{ "status": "open", "note": "<one line>" }`,
94
+ `null` when nothing broke. An open incident leaves the review incomplete until the caller fixes
95
+ it and you resume; then set `status: "resolved"`. Write no disposition document about it.
96
+ - `passes` holds, for a finished pass, `done`, `skipped: no spec found`,
97
+ `skipped: no standards found`, or
98
+ `skipped: not applicable: <reason>`. Any other value leaves the review incomplete. Never
99
+ `partial`, and never mark unfinished work skipped: a pass you did not finish is `unfinished`,
100
+ which correctly marks the whole review incomplete.
101
+ - `commands` lists the checks you ran against the code. Leave out this skill's update check and its
102
+ scripts (`pr-context.mjs`, `scan-diff.mjs`, `rereview-scope.mjs`): a caller reads a non-empty
103
+ list as proof the code was checked.
104
+ - `trigger` is required on P0/P1: the input, state, or sequence that breaks it.
105
+ - `rule` and `paths` are required on P0/P1, with at least one row `open`: the rule as one
106
+ sentence, and one row per path the diff adds, changes, or relies on (a writer, caller, sweep
107
+ place, or async cell), each `open` or `closed`, a closed row citing its guard's `file:line`.
108
+ A spec finding's `rule` is the criterion and its rows the places it must hold. When every row
109
+ is closed the finding is resolved: leave it out. A sweep's unenforced points are its finding's
110
+ open rows; `finding` names that id.
111
+ - `round` counts review attempts, skip records included, and names their files. `fixRound`
112
+ starts at `1`; on later rounds copy `rereview-scope.mjs`'s value, never your own. It is the
113
+ caller's fix counter: the tier never changes it.
114
+ - `tier` is `full` or `delta` (see [Review tiers](../SKILL.md#review-tiers)). Never write a
115
+ `scope` field.
116
+ - `mergeBase`, `patchId`, `patchFingerprint`, `tier`,
117
+ `fixLinesSinceFull` (`0` on a full round; the script's value on a delta), and `sweeps` (each
118
+ enforcement-point sweep: the rule and one row per place) let the next round run
119
+ `rereview-scope.mjs` and re-check the sweeps instead of redoing them. Take `mergeBase` and
120
+ `patchId` and `patchFingerprint` from `pr-context` on a full round and from
121
+ `rereview-scope.mjs` on a delta; `null` for an empty diff. The fingerprint also
122
+ preserves edit locations and binary bytes: patch-id alone cannot prove equivalence.
123
+ A reachable prior HEAD uses the actual PR-file tree diff; an unavailable prior HEAD
124
+ needs both matching identities, otherwise review in full. Empty `sweeps` is `[]`.
125
+ - On a delta, retain the tier decision (`reasons`, `integrationFiles`, `integrationLines`,
126
+ `baseMovedFiles`, and prior HEAD) so carry-forward approval names what was checked.
127
+ - `windows` lists each async step the change relies on, every caller of it you found (timers,
128
+ push events, expiry, and error handlers too), the events it was checked against, and for each
129
+ outcome (success, refusal, error, timeout) what the code did or the guard that rules the cell
130
+ out; `[]` when the diff has none.
131
+ - `boundaries` lists each regex, glob, parser, or validator the diff adds or changes with the
132
+ inputs tried against it; `[]` when the diff has none.
133
+ - On a re-review, keep a prior finding's `id` while its rule is broken anywhere, with every
134
+ row updated; a new witness of that rule is a new row, never a new id.
135
+
136
+ ## The skip record
137
+
138
+ You never write one by hand. On a skip, `rereview-scope.mjs --write-skip <path>` writes it in
139
+ place of review findings, whether you or the caller ran the script: `tier: "skip"`,
140
+ `carriedFrom` (the HEAD whose approval it carries), the new HEAD and patch identities, `round`
141
+ (the previous plus one), `fixRound` and `fixLinesSinceFull` carried over, `complete: true`, the
142
+ previous `passes` and `sweeps`, `commands: []` and `findings: []`. It claims no checks; CI on its
143
+ HEAD is the proof. A caller confirms it against the history and the scripts rather than trusting
144
+ the file. The next round uses a skip record as its previous result like any other.
145
+
146
+ ## Follow-ups
147
+
148
+ When the caller asks, file one issue per P2 before writing the file:
149
+ search for an existing one first, link it to the PR and the spec, and put its URL in
150
+ `followUpUrl`. When the caller says to file none, give each P2 its `file` and `line`; the
151
+ caller records it and writes its `dropboxId`. You change no code and push nothing.
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const DAY_MS = 24 * 60 * 60 * 1000;
9
+ const WEEK_MS = 7 * DAY_MS;
10
+ const here = dirname(fileURLToPath(import.meta.url));
11
+
12
+ function readJson(path, fallback = {}) {
13
+ try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return fallback; }
14
+ }
15
+
16
+ function frontmatterValue(text, key) {
17
+ const frontmatter = /^---\n([\s\S]*?)\n---/.exec(text)?.[1] ?? '';
18
+ const match = new RegExp('^' + key + ':\\s*([^\\n]+)$', 'm').exec(frontmatter);
19
+ return match?.[1].trim().replace(/^['"]|['"]$/g, '') ?? null;
20
+ }
21
+
22
+ function repositoryOf(source) {
23
+ const value = String(source ?? '').trim();
24
+ const match = /^(?:git@github\.com:|https:\/\/github\.com\/)?([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(value);
25
+ return match?.[1] ?? null;
26
+ }
27
+
28
+ function stableVersion(value) {
29
+ const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(String(value ?? '').trim());
30
+ return match ? match.slice(1).map(Number) : null;
31
+ }
32
+
33
+ function newer(left, right) {
34
+ for (let index = 0; index < 3; index += 1) {
35
+ if (left[index] !== right[index]) return left[index] > right[index];
36
+ }
37
+ return false;
38
+ }
39
+
40
+ function writeCache(path, value) {
41
+ try {
42
+ mkdirSync(dirname(path), { recursive: true });
43
+ writeFileSync(path, JSON.stringify(value));
44
+ } catch { /* A read-only cache must not block skill use. */ }
45
+ }
46
+
47
+ function main(now = Date.now()) {
48
+ if (process.env.ONEABOVEIO_NO_UPDATE_CHECK) return;
49
+ const skill = readFileSync(join(here, 'SKILL.md'), 'utf8');
50
+ const name = frontmatterValue(skill, 'name');
51
+ const localVersion = stableVersion(frontmatterValue(skill, 'release-version'));
52
+ if (!name || !localVersion) return;
53
+
54
+ const lock = readJson(join(process.env.HOME || homedir(), '.agents', '.skill-lock.json'));
55
+ const entry = lock.skills?.[name];
56
+ const repository = repositoryOf(entry?.sourceUrl || entry?.source);
57
+ if (!repository) return;
58
+
59
+ const cacheRoot = process.env.XDG_CACHE_HOME || join(process.env.HOME || homedir(), '.cache');
60
+ const cachePath = join(cacheRoot, '1aboveio-skills', 'release-check.json');
61
+ const all = readJson(cachePath);
62
+ const cache = all[repository] && typeof all[repository] === 'object' ? all[repository] : {};
63
+
64
+ if (!cache.lastCheck || now - cache.lastCheck >= DAY_MS) {
65
+ const result = spawnSync('gh', ['api', 'repos/' + repository + '/releases/latest', '--jq', '.tag_name'], {
66
+ encoding: 'utf8',
67
+ stdio: ['ignore', 'pipe', 'ignore'],
68
+ timeout: 1500,
69
+ });
70
+ cache.lastCheck = now;
71
+ if (result.status === 0 && stableVersion(result.stdout)) cache.latestTag = result.stdout.trim();
72
+ else delete cache.latestTag;
73
+ all[repository] = cache;
74
+ writeCache(cachePath, all);
75
+ }
76
+
77
+ const latestVersion = stableVersion(cache.latestTag);
78
+ if (!latestVersion || !newer(latestVersion, localVersion)) return;
79
+ if (cache.notifiedTag === cache.latestTag && cache.notifiedAt && now - cache.notifiedAt < WEEK_MS) return;
80
+
81
+ cache.notifiedTag = cache.latestTag;
82
+ cache.notifiedAt = now;
83
+ all[repository] = cache;
84
+ writeCache(cachePath, all);
85
+ const command = `npx skills@1.5.23 add '${repository}#${cache.latestTag}' --global --agent universal claude-code --skill ${name} --yes`;
86
+ process.stdout.write(
87
+ `UPDATE_AVAILABLE: A newer 1AboveIO skills release (${cache.latestTag}) is available; this skill is `
88
+ + `v${localVersion.join('.')}. Ask once whether to refresh ${name}. On approval run \`${command}\`. `
89
+ + 'The refreshed instructions apply next session. Either way, continue the current task and do not ask again this session.\n',
90
+ );
91
+ }
92
+
93
+ try { main(); } catch { /* Update checks are advisory and always fail silent. */ }
@@ -0,0 +1,212 @@
1
+ // Establish the review SUBJECT correctly, every time: the net three-dot diff from
2
+ // the merge-base, the changed files, and the commit list (for the history scan).
3
+ // Pure git — language-agnostic. Pure parsers are unit-tested; git calls live in
4
+ // the CLI. Removes the classic diff-discipline footgun (two-dot vs three-dot, wrong
5
+ // base) so the reviewer reasons over the right change-set.
6
+ //
7
+ // node pr-context.mjs --base main [--head HEAD] [--head-ref <branch-name>]
8
+ // # prints JSON review context
9
+ //
10
+ // The range it emits is `<merge-base>...HEAD` (three-dot = what would merge), which
11
+ // is what references/passes.md requires.
12
+ //
13
+ // PROMOTION SIGNAL. `promotion: true` marks a release/integration branch being merged
14
+ // into production (review as a release: fast-forward gate + readiness checklist, not a
15
+ // line-by-line re-review). It requires BOTH halves: the BASE is a production branch
16
+ // (main/master/production/prod) AND the HEAD is a recognized integration/release branch
17
+ // (dev, develop, release/*, hotfix/*, staging, staging/*). A base check alone is wrong
18
+ // in a trunk-based repo, where every feature PR targets `main` — those are feature PRs,
19
+ // not promotions (see issue #392).
20
+ //
21
+ // The head is classified by its BRANCH NAME. `--head` is a rev (default HEAD); the name
22
+ // is resolved from it (`git rev-parse --abbrev-ref`), or you may pass it explicitly with
23
+ // `--head-ref`. When the name cannot be resolved (a detached HEAD or a bare SHA — nothing
24
+ // to classify), the SAFE DEFAULT is `promotion: false`: treating a real promotion as a
25
+ // feature PR just runs the normal review; the reverse (issue #392's bug) mis-routes it.
26
+
27
+ import { execFileSync } from 'node:child_process'
28
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
29
+ import { prPatchId, prPatchFingerprint } from './rereview-scope.mjs'
30
+
31
+ // ---- pure core ----
32
+
33
+ export function threeDotRange(base, head = 'HEAD') {
34
+ return `${base}...${head}`
35
+ }
36
+
37
+ // Parse `git diff --name-status <range>` → [{status, path}] (handles rename "R100\told\tnew").
38
+ export function parseNameStatus(text) {
39
+ return (text || '').split(/\r?\n/).filter(Boolean).map((line) => {
40
+ const parts = line.split('\t')
41
+ const status = parts[0]
42
+ const path = status.startsWith('R') || status.startsWith('C') ? parts[parts.length - 1] : parts[1]
43
+ return { status, path }
44
+ })
45
+ }
46
+
47
+ // Parse `git log --oneline <base>..HEAD` → [{sha, subject}] (two-dot here is correct:
48
+ // the commits unique to the PR head).
49
+ export function parseLog(text) {
50
+ return (text || '').split(/\r?\n/).filter(Boolean).map((line) => {
51
+ const sp = line.indexOf(' ')
52
+ return sp === -1 ? { sha: line, subject: '' } : { sha: line.slice(0, sp), subject: line.slice(sp + 1) }
53
+ })
54
+ }
55
+
56
+ // A promotion (e.g. dev→main) must FAST-FORWARD: the base must be an ancestor of
57
+ // HEAD, i.e. no commits live on base that HEAD lacks. A non-empty list = base has
58
+ // commits (usually hotfixes) the promotion would REVERT — hold and back-merge first.
59
+ export function fastForwardable(commitsOnBaseNotInHead) {
60
+ return (commitsOnBaseNotInHead || []).length === 0
61
+ }
62
+
63
+ // A promotion TARGET: the base is a production branch. Necessary but NOT sufficient —
64
+ // a promotion also needs an integration/release HEAD (see isPromotion). Keying on this
65
+ // alone flags every feature PR in a trunk-based repo as a promotion (issue #392).
66
+ export function isPromotionTarget(baseRef) {
67
+ return /(^|\/)(main|master|production|prod)$/.test(baseRef || '')
68
+ }
69
+
70
+ // Conventional remote names recognized in the SHORT remote-tracking form
71
+ // (`origin/dev`). The full `refs/remotes/<remote>/…` form strips any remote segment
72
+ // because the namespace is explicit and unambiguous; the short form is ambiguous with
73
+ // an ordinary namespaced branch (`jsmith/dev`), so we only strip a KNOWN remote — never
74
+ // an arbitrary first segment. This is normalization, not part of the integration
75
+ // allowlist.
76
+ const KNOWN_REMOTES = ['origin', 'upstream']
77
+
78
+ // Normalize a head ref to a bare branch name by stripping ONLY known ref prefixes, so
79
+ // the integration/release name (if any) lands at the START of the string. Handles the
80
+ // three git ref shapes: `refs/heads/<name>`, `refs/remotes/<remote>/<name>`, and the
81
+ // short remote-tracking `<known-remote>/<name>`. It NEVER strips an arbitrary leading
82
+ // path segment — that is exactly the any-prefix hole (issue #392) this closes: a
83
+ // namespaced feature branch like `feature/release/notes` or `jsmith/dev` keeps its
84
+ // namespace and so cannot masquerade as an integration branch.
85
+ export function normalizeHeadName(headRef) {
86
+ const name = headRef || ''
87
+ if (name.startsWith('refs/heads/')) return name.slice('refs/heads/'.length)
88
+ if (name.startsWith('refs/remotes/')) {
89
+ // drop `refs/remotes/` + exactly ONE remote segment
90
+ return name.slice('refs/remotes/'.length).replace(/^[^/]+\//, '')
91
+ }
92
+ for (const remote of KNOWN_REMOTES) {
93
+ if (name.startsWith(`${remote}/`)) return name.slice(remote.length + 1)
94
+ }
95
+ return name
96
+ }
97
+
98
+ // A promotion HEAD: an integration or release branch, by NAME. A small, documented
99
+ // allowlist of integration/release shapes — dev/develop, staging, and release/hotfix/
100
+ // staging/*. After normalizing away known ref prefixes (`refs/heads/`, `refs/remotes/`,
101
+ // and short `origin/`-style remotes), the integration name is matched ANCHORED AT THE
102
+ // START (`^`): the exact whole-name shapes (`dev`/`develop`/`staging`) and the path
103
+ // shapes (`release/`/`hotfix/`/`staging/`). The name must OPEN the branch, never be
104
+ // buried under a namespace — so `origin/dev` and `refs/heads/develop` resolve, but a
105
+ // namespaced feature branch like `feature/release/notes` or `jsmith/dev` does not.
106
+ // Anything else (the common case: an ordinary feature branch, or an unresolvable bare
107
+ // SHA) → false.
108
+ export function isIntegrationBranch(headRef) {
109
+ const name = normalizeHeadName(headRef)
110
+ // exact whole-name integration branches: dev, develop, staging
111
+ if (/^(dev|develop|staging)$/.test(name)) return true
112
+ // release-family branches with a version/name suffix, name at the START: release/*, hotfix/*, staging/*
113
+ if (/^(release|hotfix|staging)\//.test(name)) return true
114
+ return false
115
+ }
116
+
117
+ // A PROMOTION = a production BASE receiving an integration/release HEAD. Both halves
118
+ // required. Review it as a release (fast-forward gate + readiness checklist), not a
119
+ // line-by-line re-review of feature code already merged & green on the integration
120
+ // branch. An unresolvable head (bare SHA → not integration-shaped) yields false, the
121
+ // documented safe default.
122
+ export function isPromotion(baseRef, headRef) {
123
+ return isPromotionTarget(baseRef) && isIntegrationBranch(headRef)
124
+ }
125
+
126
+ // The reviewer-facing note for the emitted context. Pure so the promotion branches are
127
+ // unit-testable without git. The PROMOTION + NOT fast-forwardable hold-and-back-merge
128
+ // guidance is unchanged — only the trigger (isPromotion) is corrected.
129
+ export function reviewNote({ promotion, fastForwardable: ff, base, head, commitsOnBaseNotInHead }) {
130
+ if (promotion && !ff) {
131
+ const n = (commitsOnBaseNotInHead || []).length
132
+ return `PROMOTION + NOT fast-forwardable: ${base} has ${n} commit(s) not in ${head} (likely hotfixes). HOLD — back-merge ${base} → ${head} first; promoting would revert them. Then apply the release-readiness checklist (migrations/secrets/flag-defaults/version/rollback).`
133
+ }
134
+ if (promotion) {
135
+ return 'PROMOTION (fast-forwardable): do not re-review feature code already merged & green on the integration branch. Run only the release-readiness checklist on the content: migrations/backfills, secrets & config, feature-flag defaults, version/changelog, rollback.'
136
+ }
137
+ return 'Review the NET diff (range above), not commit-by-commit. Scope findings to what this range introduces; pre-existing issues (present at mergeBase) are notes, not blockers. Scan `commits` for secrets added-then-removed / unsafe intermediate states.'
138
+ }
139
+
140
+ // ---- CLI ----
141
+
142
+ function git(args) {
143
+ return execFileSync('git', args, { encoding: 'utf8' }).trim()
144
+ }
145
+
146
+ function parseArgs(argv) {
147
+ const f = { head: 'HEAD' }
148
+ for (let i = 2; i < argv.length; i++) {
149
+ const a = argv[i]
150
+ if (a.startsWith('--')) f[a.slice(2)] = argv[++i]
151
+ }
152
+ return f
153
+ }
154
+
155
+ // Resolve the head's symbolic BRANCH NAME (what isIntegrationBranch classifies), or null
156
+ // when there is nothing to classify. Prefer an explicit --head-ref; otherwise ask git for
157
+ // the symbolic name of --head. A detached HEAD (`git rev-parse --abbrev-ref` → "HEAD") or a
158
+ // bare SHA (echoed back unchanged) has no branch name → null → promotion defaults false.
159
+ function resolveHeadName(a) {
160
+ if (a['head-ref']) return a['head-ref']
161
+ const head = a.head || 'HEAD'
162
+ let name
163
+ try {
164
+ name = git(['rev-parse', '--abbrev-ref', head])
165
+ } catch {
166
+ return null
167
+ }
168
+ if (!name || name === 'HEAD' || /^[0-9a-f]{7,40}$/i.test(name)) return null
169
+ return name
170
+ }
171
+
172
+ function main() {
173
+ const a = parseArgs(process.argv)
174
+ if (!a.base) {
175
+ console.error('usage: pr-context.mjs --base <target-branch-or-ref> [--head HEAD] [--head-ref <branch-name>]')
176
+ process.exit(2)
177
+ }
178
+ const base = git(['merge-base', a.base, a.head])
179
+ const range = threeDotRange(base, a.head)
180
+ const files = parseNameStatus(git(['diff', '--name-status', range]))
181
+ const commits = parseLog(git(['log', '--oneline', `${base}..${a.head}`]))
182
+ const diffstat = git(['diff', '--shortstat', range])
183
+ // commits on the base that HEAD lacks (in base, not in head) — the fast-forward / drift signal
184
+ const commitsOnBaseNotInHead = parseLog(git(['log', '--oneline', `${a.head}..${a.base}`]))
185
+ const ff = fastForwardable(commitsOnBaseNotInHead)
186
+ // Promotion requires BOTH a production base AND an integration/release head — a base
187
+ // check alone flags every feature→main PR (issue #392). headRef is the resolved head
188
+ // branch name (null when unresolvable → not integration-shaped → promotion false).
189
+ const headRef = resolveHeadName(a)
190
+ const promotion = isPromotion(a.base, headRef)
191
+ const ctx = {
192
+ targetRef: a.base,
193
+ headRef,
194
+ mergeBase: base,
195
+ // Write it into the result: a later round uses it to reuse this review across a
196
+ // content-equivalent rebase (rereview-scope.mjs).
197
+ patchId: prPatchId(base, a.head),
198
+ patchFingerprint: prPatchFingerprint(base, a.head),
199
+ range,
200
+ diffCommand: `git diff ${range}`,
201
+ changedFiles: files,
202
+ commits,
203
+ diffstat,
204
+ promotion,
205
+ fastForwardable: ff,
206
+ commitsOnBaseNotInHead,
207
+ note: reviewNote({ promotion, fastForwardable: ff, base: a.base, head: a.head, commitsOnBaseNotInHead }),
208
+ }
209
+ console.log(JSON.stringify(ctx, null, 2))
210
+ }
211
+
212
+ if (isMainModule(import.meta.url)) main()
@@ -0,0 +1,168 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { threeDotRange, parseNameStatus, parseLog, fastForwardable, isPromotionTarget, isIntegrationBranch, isPromotion, reviewNote, normalizeHeadName } from './pr-context.mjs'
4
+
5
+ test('threeDotRange uses three dots (the merge diff, not two-dot)', () => {
6
+ assert.equal(threeDotRange('abc123'), 'abc123...HEAD')
7
+ assert.equal(threeDotRange('abc', 'feat'), 'abc...feat')
8
+ })
9
+
10
+ test('parseNameStatus handles add/modify/delete and rename', () => {
11
+ const text = ['M\tsrc/a.ts', 'A\tsrc/new.ts', 'D\tsrc/old.ts', 'R100\tsrc/from.ts\tsrc/to.ts'].join('\n')
12
+ assert.deepEqual(parseNameStatus(text), [
13
+ { status: 'M', path: 'src/a.ts' },
14
+ { status: 'A', path: 'src/new.ts' },
15
+ { status: 'D', path: 'src/old.ts' },
16
+ { status: 'R100', path: 'src/to.ts' },
17
+ ])
18
+ })
19
+
20
+ test('parseNameStatus empty → []', () => {
21
+ assert.deepEqual(parseNameStatus(''), [])
22
+ })
23
+
24
+ test('parseLog splits sha + subject', () => {
25
+ const text = '1a2b3c add export\n4d5e6f fix expired coupon'
26
+ assert.deepEqual(parseLog(text), [
27
+ { sha: '1a2b3c', subject: 'add export' },
28
+ { sha: '4d5e6f', subject: 'fix expired coupon' },
29
+ ])
30
+ })
31
+
32
+ test('fastForwardable: empty = FF possible; non-empty (base has commits head lacks) = not FF', () => {
33
+ assert.equal(fastForwardable([]), true)
34
+ assert.equal(fastForwardable([{ sha: 'h0tf1x', subject: 'hotfix prod' }]), false)
35
+ assert.equal(fastForwardable(undefined), true)
36
+ })
37
+
38
+ test('isPromotionTarget: production branches only (the base half of a promotion)', () => {
39
+ assert.equal(isPromotionTarget('main'), true)
40
+ assert.equal(isPromotionTarget('master'), true)
41
+ assert.equal(isPromotionTarget('production'), true)
42
+ assert.equal(isPromotionTarget('origin/main'), true)
43
+ assert.equal(isPromotionTarget('dev'), false)
44
+ assert.equal(isPromotionTarget('feature/x'), false)
45
+ assert.equal(isPromotionTarget('release/1.2'), false)
46
+ })
47
+
48
+ test('isIntegrationBranch: only integration/release-shaped heads (the head half of a promotion)', () => {
49
+ // integration branches
50
+ assert.equal(isIntegrationBranch('dev'), true)
51
+ assert.equal(isIntegrationBranch('develop'), true)
52
+ assert.equal(isIntegrationBranch('origin/dev'), true)
53
+ assert.equal(isIntegrationBranch('refs/heads/develop'), true)
54
+ // release / hotfix / staging shapes
55
+ assert.equal(isIntegrationBranch('release/1.4'), true)
56
+ assert.equal(isIntegrationBranch('release/2.0.0'), true)
57
+ assert.equal(isIntegrationBranch('hotfix/urgent-fix'), true)
58
+ assert.equal(isIntegrationBranch('staging'), true)
59
+ assert.equal(isIntegrationBranch('staging/eu'), true)
60
+ assert.equal(isIntegrationBranch('origin/release/1.4'), true)
61
+ // ordinary feature branches — NOT integration
62
+ assert.equal(isIntegrationBranch('feature/x'), false)
63
+ assert.equal(isIntegrationBranch('chore/388-doc-code-prose-audit'), false)
64
+ assert.equal(isIntegrationBranch('issue-392-promotion-heuristic'), false)
65
+ assert.equal(isIntegrationBranch('main'), false)
66
+ assert.equal(isIntegrationBranch('develop-tweaks'), false) // not exactly `develop`
67
+ assert.equal(isIntegrationBranch('feature/release-notes'), false) // `release` not its own segment
68
+ // unresolvable head (a bare SHA, or empty) — NOT integration → safe default
69
+ assert.equal(isIntegrationBranch('a1b2c3d'), false)
70
+ assert.equal(isIntegrationBranch(''), false)
71
+ assert.equal(isIntegrationBranch(undefined), false)
72
+ })
73
+
74
+ test('isPromotion: true ONLY when base is production AND head is integration/release-shaped', () => {
75
+ // the ~15x false-positive this fixes: a feature branch → main is NOT a promotion
76
+ assert.equal(isPromotion('main', 'chore/388-doc-code-prose-audit'), false)
77
+ assert.equal(isPromotion('main', 'feature/x'), false)
78
+ assert.equal(isPromotion('main', 'issue-392-promotion-heuristic'), false)
79
+ // genuine promotions: integration/release branch → production
80
+ assert.equal(isPromotion('main', 'dev'), true)
81
+ assert.equal(isPromotion('main', 'release/1.4'), true)
82
+ assert.equal(isPromotion('main', 'hotfix/x'), true)
83
+ assert.equal(isPromotion('master', 'develop'), true)
84
+ assert.equal(isPromotion('origin/main', 'origin/dev'), true)
85
+ // base is not a production branch → never a promotion, even from an integration head
86
+ assert.equal(isPromotion('dev', 'feature/x'), false)
87
+ assert.equal(isPromotion('release/1.4', 'dev'), false)
88
+ // unresolvable head (bare SHA / empty) → false (documented safe default)
89
+ assert.equal(isPromotion('main', 'a1b2c3d'), false)
90
+ assert.equal(isPromotion('main', ''), false)
91
+ assert.equal(isPromotion('main', undefined), false)
92
+ })
93
+
94
+ test('normalizeHeadName strips ONLY known ref prefixes — never an arbitrary leading segment', () => {
95
+ // known ref prefixes → stripped to the bare name
96
+ assert.equal(normalizeHeadName('refs/heads/develop'), 'develop')
97
+ assert.equal(normalizeHeadName('refs/remotes/origin/release/1.4'), 'release/1.4')
98
+ assert.equal(normalizeHeadName('origin/dev'), 'dev')
99
+ assert.equal(normalizeHeadName('origin/release/1.4'), 'release/1.4')
100
+ assert.equal(normalizeHeadName('upstream/staging'), 'staging')
101
+ // NOT a known prefix → left intact (the any-prefix hole this closes)
102
+ assert.equal(normalizeHeadName('jsmith/dev'), 'jsmith/dev')
103
+ assert.equal(normalizeHeadName('feature/release/notes'), 'feature/release/notes')
104
+ assert.equal(normalizeHeadName('team/staging/eu'), 'team/staging/eu')
105
+ // plain names pass through
106
+ assert.equal(normalizeHeadName('dev'), 'dev')
107
+ assert.equal(normalizeHeadName('release/1.4'), 'release/1.4')
108
+ assert.equal(normalizeHeadName(''), '')
109
+ assert.equal(normalizeHeadName(undefined), '')
110
+ })
111
+
112
+ // LEFT-BOUNDARY REGRESSION (issue #392, fix round): the integration/release name must
113
+ // open the branch (after ref-prefix stripping), never be buried under a namespace. A
114
+ // nested-prefix feature branch is an ordinary feature PR, not a promotion — the unsafe
115
+ // direction if mis-classified. Removing the `^`/normalization makes these go RED.
116
+ test('isIntegrationBranch: nested-prefix feature branches are NOT integration (left-boundary hole)', () => {
117
+ // line-79 (release/hotfix/staging path) hole
118
+ assert.equal(isIntegrationBranch('feature/release/notes'), false)
119
+ assert.equal(isIntegrationBranch('feature/hotfix/x'), false)
120
+ assert.equal(isIntegrationBranch('team/staging/eu'), false)
121
+ // line-77 (exact dev/develop/staging) hole
122
+ assert.equal(isIntegrationBranch('jsmith/dev'), false)
123
+ assert.equal(isIntegrationBranch('alice/develop'), false)
124
+ assert.equal(isIntegrationBranch('wip/staging'), false)
125
+ })
126
+
127
+ test('isIntegrationBranch: supported ref prefixes still resolve to TRUE after normalization', () => {
128
+ assert.equal(isIntegrationBranch('origin/dev'), true)
129
+ assert.equal(isIntegrationBranch('refs/heads/develop'), true)
130
+ assert.equal(isIntegrationBranch('refs/remotes/origin/release/1.4'), true)
131
+ })
132
+
133
+ test('isPromotion: nested-prefix feature branches → main are NOT promotions (left-boundary hole)', () => {
134
+ // these all classified promotion=true before the anchor fix (the fail-open direction)
135
+ assert.equal(isPromotion('main', 'feature/release/notes'), false)
136
+ assert.equal(isPromotion('main', 'feature/hotfix/x'), false)
137
+ assert.equal(isPromotion('main', 'team/staging/eu'), false)
138
+ assert.equal(isPromotion('main', 'jsmith/dev'), false)
139
+ assert.equal(isPromotion('main', 'alice/develop'), false)
140
+ assert.equal(isPromotion('main', 'wip/staging'), false)
141
+ // supported prefixes remain genuine promotions
142
+ assert.equal(isPromotion('main', 'refs/heads/develop'), true)
143
+ assert.equal(isPromotion('main', 'refs/remotes/origin/release/1.4'), true)
144
+ })
145
+
146
+ test('reviewNote: PROMOTION + NOT fast-forwardable note still fires for a genuine promotion that is not FF', () => {
147
+ const note = reviewNote({
148
+ promotion: true,
149
+ fastForwardable: false,
150
+ base: 'main',
151
+ head: 'release/1.4',
152
+ commitsOnBaseNotInHead: [{ sha: 'h0tf1x', subject: 'hotfix prod' }],
153
+ })
154
+ assert.match(note, /PROMOTION \+ NOT fast-forwardable/)
155
+ assert.match(note, /main has 1 commit\(s\) not in release\/1\.4/)
156
+ assert.match(note, /HOLD/)
157
+ })
158
+
159
+ test('reviewNote: fast-forwardable promotion → release-readiness note (not a re-review)', () => {
160
+ const note = reviewNote({ promotion: true, fastForwardable: true, base: 'main', head: 'dev', commitsOnBaseNotInHead: [] })
161
+ assert.match(note, /PROMOTION \(fast-forwardable\)/)
162
+ assert.doesNotMatch(note, /NOT fast-forwardable/)
163
+ })
164
+
165
+ test('reviewNote: not a promotion → review the NET diff (the common feature-PR path)', () => {
166
+ const note = reviewNote({ promotion: false, fastForwardable: true, base: 'main', head: 'feature/x', commitsOnBaseNotInHead: [] })
167
+ assert.match(note, /Review the NET diff/)
168
+ })