@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,503 @@
1
+ // Pick the review tier for a new HEAD, from the previous round's result file.
2
+ //
3
+ // node rereview-scope.mjs --prior <previous-result.json> --base <target-branch> [--head HEAD]
4
+ // [--write-skip <next-result.json>]
5
+ //
6
+ // Prints JSON with `tier`:
7
+ // skip no reviewer runs: the previous review passed and the PR's own changes are unchanged
8
+ // (the same HEAD; the same patch over a base that moved only outside the PR's files;
9
+ // or, with both reviewed commits at hand, every PR file's own changed lines the same,
10
+ // at the same places, after the base moved under them).
11
+ // With --write-skip, the script writes the record that carries the approval to
12
+ // this HEAD; CI on this HEAD is the proof.
13
+ // delta review `touchedFiles` (fix commits, and PR files the base moved under) in full
14
+ // depth and re-check `carriedFiles` only where they depend on what changed.
15
+ // full review the whole diff again; `reasons` names each trigger.
16
+ // The reviewer may widen the tier, never narrow it.
17
+ //
18
+ // A skip needs a previous review that is complete, anchored, and has no open P0/P1: a
19
+ // blocker is never carried, it is fixed. A delta is allowed only when the previous round covered the whole diff (every pass done
20
+ // or skipped for a stated reason, not oversize), and the fixes and integration changes
21
+ // since the last full round changed at most half the PR's lines in total. Conflicted
22
+ // files join the delta as `integrationFiles`; imported base lines do not count as fixes.
23
+ // Unbounded integration impact forces full. The base diff remains mandatory review input.
24
+ // Neither the round number nor a previous delta forces full: impact does. A rebase or
25
+ // metadata-only commit that leaves the PR's own patch unchanged reuses the review, even
26
+ // when the reviewed HEAD is gone, using a location-sensitive `patchFingerprint` as well
27
+ // as `patchId`. A reachable prior HEAD must also have no changed PR-file content before
28
+ // its source approval can carry. Anything this script cannot establish (unreachable
29
+ // history without both identities, or missing fields) forces full.
30
+ //
31
+ // The result file of each round records `patchId`, `patchFingerprint` and
32
+ // `fixLinesSinceFull` from this output (round 1 takes the identities from pr-context
33
+ // and `fixLinesSinceFull: 0`).
34
+ //
35
+ // On a delta it also hands the reviewer its setup, so the round starts reviewing at once:
36
+ // the open P0/P1 findings in full, the previous sweep points that sit in touched files, the
37
+ // names the fix diff defines or changes, every line in a carried file that uses one of them,
38
+ // and scan-diff's leads and findings for the fix diff alone.
39
+ //
40
+ // Exit codes: 0 tier printed, 2 usage error or unreadable prior result.
41
+
42
+ import { execFileSync } from 'node:child_process'
43
+ import { createHash } from 'node:crypto'
44
+ import fs from 'node:fs'
45
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
46
+ import { reviewCompletionProblems, reviewTier } from '../../engineering-runtime/scripts/review-completion.mjs'
47
+ import { scanDiff } from './scan-diff.mjs'
48
+
49
+ export const MAX_FIX_SHARE = 0.5
50
+ export const MAX_CALL_SITES = 200
51
+ export const MAX_FIX_DIFF_CHARS = 60000
52
+
53
+ const USAGE = 'usage: rereview-scope.mjs --prior <previous-result.json> --base <target-branch> [--head HEAD] [--write-skip <next-result.json>]'
54
+ export const TIERS = Object.freeze(['skip', 'delta', 'full'])
55
+ const isBlocking = (f) => f?.severity === 'P0' || f?.severity === 'P1'
56
+
57
+ export class RereviewScopeError extends Error {}
58
+
59
+ // ---- pure core ----
60
+
61
+ // Reasons the previous result cannot anchor a delta. Empty means it can.
62
+ export function priorProblems(prior) {
63
+ const problems = reviewCompletionProblems(prior, { requirePasses: true }).map((problem) => `previous ${problem}`)
64
+ if (typeof prior?.head !== 'string' || prior.head.trim() === '') problems.push('previous result has no head')
65
+ if (typeof prior?.mergeBase !== 'string' || prior.mergeBase.trim() === '') problems.push('previous result has no mergeBase')
66
+ if (!Number.isInteger(prior?.round) || prior.round < 1) problems.push('previous result has no round')
67
+ const tier = reviewTier(prior)
68
+ if (tier !== undefined && !TIERS.includes(tier)) problems.push(`previous round has unknown tier ${JSON.stringify(tier)}`)
69
+ if ((tier === 'delta' || tier === 'skip') && !(Number.isInteger(prior.fixLinesSinceFull) && prior.fixLinesSinceFull >= 0)) {
70
+ problems.push(`previous ${tier} round has no fixLinesSinceFull`)
71
+ }
72
+ if (prior?.oversize === true) problems.push('previous round was oversize')
73
+ if (Object.hasOwn(prior ?? {}, 'fixRound') && (!Number.isSafeInteger(prior.fixRound) || prior.fixRound < 1 || prior.fixRound > prior.round)) {
74
+ problems.push('previous fixRound must be a positive safe integer no greater than round')
75
+ }
76
+
77
+ return problems
78
+ }
79
+
80
+ // Sum added + deleted lines from `git diff --numstat` output; binary files count as 1.
81
+ export function numstatLines(text) {
82
+ let total = 0
83
+ for (const line of (text || '').split('\n')) {
84
+ const m = line.match(/^(\d+|-)\t(\d+|-)\t/)
85
+ if (!m) continue
86
+ total += m[1] === '-' ? 1 : Number(m[1]) + Number(m[2])
87
+ }
88
+ return total
89
+ }
90
+
91
+ // `samePatch`: the reviewed HEAD is gone, but the PR's own patch is identical to the one
92
+ // reviewed (a content-equivalent rebase), so nothing in the PR changed.
93
+ // `conflictFiles`: PR files the base moved under whose own PR changes also changed.
94
+ // `baseKnown`: the previous merge-base is in this repository, so base movement is known.
95
+ // `sameHead`: the HEAD is the one the previous round reviewed.
96
+ // `ownUnchanged`: every PR file's own changed lines are the ones reviewed, at the same places
97
+ // once the base's own edits are mapped out; only the base moved. CI on the new HEAD proves
98
+ // how the two fit together.
99
+ export function decideScope({ prior, round, prFiles, touchedFiles, baseMovedFiles, fixLines, prLines, priorHeadReachable, samePatch = false, sameHead = false, conflictFiles = [], integrationLines = 0, baseKnown = true, ownUnchanged = false }) {
100
+ const reasons = [...priorProblems(prior)]
101
+ if (!priorHeadReachable && !samePatch) reasons.push(`previous HEAD ${prior?.head} is not in this repository and its patch identities differ or are missing`)
102
+ if (!baseKnown) reasons.push(`previous merge-base ${prior?.mergeBase} is not in this repository`)
103
+ const prSet = new Set(prFiles)
104
+ const conflicts = new Set(conflictFiles)
105
+ const underPr = baseMovedFiles.filter((file) => prSet.has(file))
106
+ const conflicted = underPr.filter((file) => conflicts.has(file))
107
+ if (integrationLines === null) reasons.push('integration impact cannot be bounded; review the whole diff')
108
+ const mergeFiles = underPr.filter((file) => !conflicts.has(file))
109
+ const sinceFull = (reviewTier(prior) !== undefined && reviewTier(prior) !== 'full' && Number.isInteger(prior.fixLinesSinceFull) ? prior.fixLinesSinceFull : 0) + fixLines + (integrationLines ?? 0)
110
+ if (prLines > 0 && sinceFull / prLines > MAX_FIX_SHARE) {
111
+ reasons.push(`the fixes since the last full review changed ${sinceFull} of ${prLines} PR lines (more than ${MAX_FIX_SHARE * 100}%)`)
112
+ }
113
+ if (prLines === 0 && sinceFull > 0) reasons.push('the previously reviewed PR changes were removed')
114
+ const touched = new Set([...touchedFiles, ...mergeFiles, ...conflicted])
115
+ const passed = Array.isArray(prior?.findings) && !prior.findings.some(isBlocking)
116
+ const unchanged = sameHead || (samePatch && baseKnown && underPr.length === 0) || (ownUnchanged && baseKnown && priorHeadReachable)
117
+ const tier = reasons.length > 0 ? 'full' : passed && unchanged ? 'skip' : 'delta'
118
+ return {
119
+ tier,
120
+ reasons,
121
+ round,
122
+ touchedFiles: prFiles.filter((file) => touched.has(file)),
123
+ carriedFiles: prFiles.filter((file) => !touched.has(file)),
124
+ fixLines,
125
+ integrationLines,
126
+ prLines,
127
+ fixLinesSinceFull: tier === 'full' ? 0 : sinceFull,
128
+ mergeFiles,
129
+ integrationFiles: conflicted,
130
+ }
131
+ }
132
+
133
+ // Names a diff defines or changes, from its added and removed lines (not context): top-level
134
+ // code definitions in JS/TS/Python-style syntax (unindented or exported; a local variable is
135
+ // nobody else's contract), plus Markdown headings as link anchors (`#slug`), since prose files
136
+ // link to each other by heading. Test files define nothing other code uses, so they are
137
+ // skipped. Best effort: a miss leaves the reviewer's own search as the only net, so this
138
+ // never replaces reading the fix diff.
139
+ const DEFINITION_PATTERNS = [
140
+ /^(?:export\s+(?:default\s+)?)?(?:async\s+)?(?:function\*?|class|def|interface|type|enum)\s+([A-Za-z_$][\w$]*)/,
141
+ /^(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=/,
142
+ /^\s*export\s+(?:default\s+)?(?:async\s+)?(?:function\*?|class|const|let|var|interface|type|enum)\s+([A-Za-z_$][\w$]*)/,
143
+ ]
144
+ const TEST_FILE = /(^|\/)(__tests__|tests?)\/|[._-](test|spec)\.[cm]?[jt]sx?$|(^|\/)test_[^/]*\.py$|_test\.(py|go)$/
145
+ const NOT_NAMES = new Set(['if', 'for', 'while', 'switch', 'catch', 'function', 'return', 'constructor'])
146
+
147
+ export function headingSlug(text) {
148
+ return text.trim().toLowerCase().replace(/[`*_~]/g, '').replace(/[^\p{L}\p{N}\s-]/gu, '').replace(/\s/g, '-')
149
+ }
150
+
151
+ export function changedSymbols(diffText) {
152
+ const names = new Set()
153
+ const anchors = new Set()
154
+ let file = ''
155
+ for (const raw of (diffText || '').split(/\r?\n/)) {
156
+ if (raw.startsWith('+++ ') || raw.startsWith('--- ')) { file = raw.slice(4).replace(/^[ab]\//, ''); continue }
157
+ if (!/^[+-]/.test(raw)) continue
158
+ const line = raw.slice(1)
159
+ if (/\.(md|mdx)$/i.test(file)) {
160
+ const h = line.match(/^#{1,6}\s+(.+?)\s*#*\s*$/)
161
+ if (h) anchors.add(`#${headingSlug(h[1])}`)
162
+ continue
163
+ }
164
+ if (TEST_FILE.test(file)) continue
165
+ for (const pattern of DEFINITION_PATTERNS) {
166
+ const m = line.match(pattern)
167
+ if (m && !NOT_NAMES.has(m[1]) && m[1].length > 2) names.add(m[1])
168
+ }
169
+ }
170
+ return { names: [...names].sort(), anchors: [...anchors].sort() }
171
+ }
172
+
173
+ // The previous round's sweep points whose location is a touched file.
174
+ export function sweepRecheck(prior, touchedFiles) {
175
+ const touched = new Set(touchedFiles)
176
+ const out = []
177
+ for (const sweep of prior?.sweeps ?? []) {
178
+ for (const point of sweep?.points ?? []) {
179
+ const file = String(point?.location ?? '').replace(/:\d+(?:-\d+)?$/, '')
180
+ if (touched.has(file)) out.push({ rule: sweep.rule, ...point })
181
+ }
182
+ }
183
+ return out
184
+ }
185
+
186
+ // ---- git glue ----
187
+
188
+ function git(args) {
189
+ return execFileSync('git', args, { encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 }).trim()
190
+ }
191
+
192
+ // The whitespace-preserving patch id of the PR's net diff, or null for an empty diff.
193
+ // Whitespace can change behavior (for example Python indentation), so it is not metadata.
194
+ export function prPatchId(mergeBase, head, paths = []) {
195
+ const diff = execFileSync('git', ['diff', '--binary', `${mergeBase}...${head}`, ...(paths.length ? ['--', ...paths] : [])], { encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 })
196
+ if (diff.trim() === '') return null
197
+ const out = execFileSync('git', ['patch-id', '--verbatim'], { input: diff, encoding: 'utf8' }).trim()
198
+ return out.split(/\s+/)[0] || null
199
+ }
200
+
201
+ // Unlike patch-id, this preserves hunk locations as well as whitespace and binary bytes.
202
+ // Ignore only blob ids: base edits outside the patch can change them after a rebase.
203
+ export function prPatchFingerprint(mergeBase, head) {
204
+ const diff = execFileSync('git', ['diff', '--binary', `${mergeBase}...${head}`], { encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 })
205
+ if (diff.trim() === '') return null
206
+ const patch = diff.split('\n').filter((line) => !/^index [0-9a-f]+\.\.[0-9a-f]+(?: \d+)?$/.test(line)).join('\n')
207
+ return createHash('sha256').update(patch).digest('hex')
208
+ }
209
+
210
+ // Compare the PR's own changed lines, not the old/new trees (which include base imports).
211
+ // Sequence comparison counts reordered changes too. Large or binary patches fail closed.
212
+ export function patchImpactLines(before, after, baseDiff = '') {
213
+ if (before === after) return 0
214
+ if (before.length + after.length > MAX_FIX_DIFF_CHARS * 2) return null
215
+ if (/^(?:Binary files |GIT binary patch)/m.test(before + '\n' + after)) return null
216
+ const baseHunks = [...baseDiff.matchAll(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/gm)]
217
+ .map((match) => ({ oldStart: Number(match[1]), oldCount: Number(match[2] ?? 1), newStart: Number(match[3]), newCount: Number(match[4] ?? 1) }))
218
+ // Map new-base anchors back to the reviewed base. Pure base insertions shift
219
+ // lines but not edit targets; anchors inside rewritten base hunks are new.
220
+ const reviewedAnchor = (line) => {
221
+ let offset = 0
222
+ for (const hunk of baseHunks) {
223
+ const start = hunk.newCount === 0 ? hunk.newStart + 1 : hunk.newStart
224
+ if (line < start) break
225
+ if (hunk.newCount > 0 && line < start + hunk.newCount) return `new:${line}`
226
+ offset += hunk.oldCount - hunk.newCount
227
+ }
228
+ return line + offset
229
+ }
230
+ const changed = (diff, mapAnchor = (line) => line) => {
231
+ const out = []
232
+ let hunk = false
233
+ let context = ''
234
+ let oldLine = 0
235
+ for (const line of diff.split('\n')) {
236
+ if (line.startsWith('diff --git ')) hunk = false
237
+ else if (line.startsWith('@@ ')) {
238
+ hunk = true
239
+ context = line.slice(line.indexOf(' @@') + 3)
240
+ oldLine = Number(/^@@ -(\d+)/.exec(line)?.[1])
241
+ } else if (hunk && /^[+-]/.test(line)) {
242
+ out.push(`${mapAnchor(oldLine)}\0${context}\0${line}`)
243
+ if (line.startsWith('-')) oldLine++
244
+ } else if (hunk && line.startsWith(' ')) oldLine++
245
+ }
246
+ return out
247
+ }
248
+ const a = changed(before)
249
+ const b = changed(after, reviewedAnchor)
250
+ if (a.length * b.length > 4_000_000) return null
251
+ let previous = new Uint32Array(b.length + 1)
252
+ for (const line of a) {
253
+ const current = new Uint32Array(b.length + 1)
254
+ for (let j = 1; j <= b.length; j++) {
255
+ current[j] = line === b[j - 1] ? previous[j - 1] + 1 : Math.max(previous[j], current[j - 1])
256
+ }
257
+ previous = current
258
+ }
259
+ const impact = a.length + b.length - 2 * previous[b.length]
260
+ return impact
261
+ }
262
+
263
+ // True when a file's own PR lines are the reviewed ones at the same places, once the base's
264
+ // edits are mapped out: `before` and `after` are the file's PR diffs (--unified=0) over the
265
+ // reviewed and the current base, `baseDiff` the base's own change between them. A PR insertion
266
+ // that now sits just before or after lines the base inserted at the same point kept both sides
267
+ // of a conflict, so it is unchanged; a PR line that edits or replaces a base line is not.
268
+ // Large or binary patches fail closed (false).
269
+ export function ownLinesUnchanged(before, after, baseDiff = '') {
270
+ if (before === after) return true
271
+ if (before.length + after.length > MAX_FIX_DIFF_CHARS * 2) return false
272
+ if (/^(?:Binary files |GIT binary patch)/m.test(before + '\n' + after)) return false
273
+ const hunks = (diff) => [...diff.matchAll(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/gm)]
274
+ .map((m) => ({ oldStart: Number(m[1]), oldCount: Number(m[2] ?? 1), newStart: Number(m[3]), newCount: Number(m[4] ?? 1) }))
275
+ const base = hunks(baseDiff)
276
+ // A line of the current base, as a line of the reviewed base; null inside base-rewritten lines.
277
+ const toReviewed = (line, insertion) => {
278
+ let offset = 0
279
+ for (const h of base) {
280
+ if (insertion && h.oldCount === 0 && (line === h.newStart - 1 || line === h.newStart + h.newCount - 1)) return h.oldStart
281
+ const start = h.newCount === 0 ? h.newStart + 1 : h.newStart
282
+ if (line < start) break
283
+ if (h.newCount > 0 && line < start + h.newCount) return null
284
+ offset += h.oldCount - h.newCount
285
+ }
286
+ return line + offset
287
+ }
288
+ const rows = (diff, map) => {
289
+ const out = []
290
+ let hunk = null
291
+ let oldLine = 0
292
+ for (const line of diff.split('\n')) {
293
+ if (line.startsWith('diff --git ')) hunk = null
294
+ else if (line.startsWith('@@ ')) {
295
+ const m = /^@@ -(\d+)(?:,(\d+))?/.exec(line)
296
+ hunk = { insertion: Number(m[2] ?? 1) === 0 }
297
+ oldLine = Number(m[1])
298
+ // A reviewed hunk that comes back split around base lines is a change.
299
+ out.push('@@')
300
+ } else if (hunk && /^[+-]/.test(line)) {
301
+ const at = map(oldLine, hunk.insertion)
302
+ if (at === null) return null
303
+ out.push(`${at}\0${line}`)
304
+ if (line.startsWith('-')) oldLine++
305
+ }
306
+ }
307
+ return out
308
+ }
309
+ const a = rows(before, (line) => line)
310
+ const b = rows(after, toReviewed)
311
+ return a !== null && b !== null && a.length === b.length && a.every((row, i) => row === b[i])
312
+ }
313
+
314
+ function reachable(rev) {
315
+ try { git(['cat-file', '-e', `${rev}^{commit}`]); return true } catch { return false }
316
+ }
317
+
318
+ const lines = (text) => text.split('\n').filter(Boolean)
319
+
320
+ export function parseCliArgs(argv) {
321
+ const opts = { head: 'HEAD' }
322
+ for (let i = 0; i < argv.length; i++) {
323
+ const flag = argv[i]
324
+ if (flag === '--help' || flag === '-h') return { help: true }
325
+ if (!['--prior', '--base', '--head', '--write-skip'].includes(flag)) throw new RereviewScopeError(`unknown flag ${JSON.stringify(flag)}\n${USAGE}`)
326
+ const value = argv[++i]
327
+ if (value === undefined || value.startsWith('--')) throw new RereviewScopeError(`${flag} needs a value\n${USAGE}`)
328
+ opts[flag === '--write-skip' ? 'writeSkip' : flag.slice(2)] = value
329
+ }
330
+ if (!opts.prior || !opts.base) throw new RereviewScopeError(USAGE)
331
+ return opts
332
+ }
333
+
334
+ export function rereviewScope({ prior, base, head = 'HEAD' }) {
335
+ const headSha = git(['rev-parse', head])
336
+ const mergeBase = git(['merge-base', base, headSha])
337
+ const currentPrFiles = lines(git(['diff', '--no-renames', '--name-only', `${mergeBase}...${headSha}`]))
338
+ const prLines = numstatLines(git(['diff', '--numstat', `${mergeBase}...${headSha}`]))
339
+ const round = (Number.isInteger(prior?.round) ? prior.round : 0) + 1
340
+ const priorHeadReachable = typeof prior?.head === 'string' && reachable(prior.head)
341
+ const priorBaseReachable = typeof prior?.mergeBase === 'string' && reachable(prior.mergeBase)
342
+ const patchId = prPatchId(mergeBase, headSha)
343
+ const patchFingerprint = prPatchFingerprint(mergeBase, headSha)
344
+ const priorPatchId = priorHeadReachable && priorBaseReachable ? prPatchId(prior.mergeBase, prior.head) : prior?.patchId
345
+ const priorPrFiles = priorHeadReachable && priorBaseReachable
346
+ ? lines(git(['diff', '--no-renames', '--name-only', `${prior.mergeBase}...${prior.head}`])) : []
347
+ const prFiles = [...new Set([...currentPrFiles, ...priorPrFiles])]
348
+ const treeTouched = priorHeadReachable && prFiles.length
349
+ ? lines(git(['diff', '--no-renames', '--name-only', prior.head, headSha, '--', ...prFiles])) : []
350
+ const samePatch = typeof priorPatchId === 'string' && patchId !== null && priorPatchId === patchId
351
+ && (priorHeadReachable ? treeTouched.length === 0
352
+ : typeof prior?.patchFingerprint === 'string' && patchFingerprint === prior.patchFingerprint)
353
+ let baseMovedFiles = []
354
+ if (priorBaseReachable && prior.mergeBase !== mergeBase) {
355
+ baseMovedFiles = lines(git(['diff', '--no-renames', '--name-only', prior.mergeBase, mergeBase]))
356
+ }
357
+ const prSet = new Set(prFiles)
358
+ const overlap = baseMovedFiles.filter((file) => prSet.has(file))
359
+ // A PR file the base moved under had its own PR changes altered when its per-file patch
360
+ // differs from the reviewed one: a conflict resolution or a fix landed there too.
361
+ const conflictFiles = samePatch ? [] : overlap.filter((file) => !priorHeadReachable
362
+ || prPatchId(prior.mergeBase, prior.head, [file]) !== prPatchId(mergeBase, headSha, [file]))
363
+ let touchedFiles = prFiles
364
+ let fixLines = prLines
365
+ let integrationLines = 0
366
+ if (samePatch) {
367
+ touchedFiles = []
368
+ fixLines = 0
369
+ } else if (priorHeadReachable && prFiles.length > 0) {
370
+ touchedFiles = treeTouched
371
+ // Lines the base alone changed are not fix lines. Compare overlapping PR patches separately.
372
+ const ownFiles = prFiles.filter((file) => !overlap.includes(file))
373
+ fixLines = ownFiles.length ? numstatLines(git(['diff', '--numstat', prior.head, headSha, '--', ...ownFiles])) : 0
374
+ if (priorBaseReachable) for (const file of conflictFiles) {
375
+ const before = git(['diff', '--no-renames', '--unified=0', prior.mergeBase, prior.head, '--', file])
376
+ const after = git(['diff', '--no-renames', '--unified=0', mergeBase, headSha, '--', file])
377
+ const baseDiff = git(['diff', '--no-renames', '--unified=0', prior.mergeBase, mergeBase, '--', file])
378
+ const impact = patchImpactLines(before, after, baseDiff)
379
+ if (impact === null) { integrationLines = null; break }
380
+ integrationLines += impact
381
+ }
382
+ }
383
+ const sameHead = priorHeadReachable && prior.head === headSha
384
+ // The base moved under PR files: are the PR's own lines there still the reviewed ones?
385
+ let ownUnchanged = false
386
+ if (!samePatch && priorHeadReachable && priorBaseReachable && overlap.length > 0 && fixLines === 0 && integrationLines !== null) {
387
+ ownUnchanged = overlap.every((file) => ownLinesUnchanged(
388
+ git(['diff', '--no-renames', '--unified=0', prior.mergeBase, prior.head, '--', file]),
389
+ git(['diff', '--no-renames', '--unified=0', mergeBase, headSha, '--', file]),
390
+ git(['diff', '--no-renames', '--unified=0', prior.mergeBase, mergeBase, '--', file])))
391
+ }
392
+ const decision = decideScope({ prior, round, prFiles, touchedFiles, baseMovedFiles, fixLines, integrationLines, prLines, priorHeadReachable, samePatch, sameHead, conflictFiles, baseKnown: priorBaseReachable, ownUnchanged })
393
+ const openFindings = (prior?.findings ?? []).filter(isBlocking)
394
+ const priorFixRound = prior?.fixRound ?? prior?.round
395
+ const fixRound = Number.isSafeInteger(priorFixRound) && priorFixRound >= 1
396
+ ? priorFixRound + (reviewCompletionProblems(prior).length === 0 && openFindings.length > 0 ? 1 : 0) : null
397
+ const result = {
398
+ ...decision,
399
+ fixRound,
400
+ head: headSha,
401
+ mergeBase,
402
+ patchId,
403
+ patchFingerprint,
404
+ samePatch,
405
+ priorHead: prior?.head ?? null,
406
+ baseMovedFiles,
407
+ baseDiffCommand: baseMovedFiles.length ? `git diff ${prior.mergeBase} ${mergeBase}` : null,
408
+ fixDiffCommand: null,
409
+ mergeDiffCommand: overlap.length ? `git diff ${prior.mergeBase} ${mergeBase} -- ${overlap.join(' ')}` : null,
410
+ openFindings,
411
+ }
412
+ if (decision.tier !== 'delta') return result
413
+ if (decision.touchedFiles.length === 0) {
414
+ // Nothing in the PR changed since the reviewed round: no fix diff to review.
415
+ return { ...result, fixDiff: '', sweepRecheck: [], changedSymbols: { names: [], anchors: [] }, callSites: { sites: [], truncated: false }, fixScan: { findings: [], leads: [] } }
416
+ }
417
+ // With the reviewed HEAD gone (samePatch), the only change is the merge diff.
418
+ const fixDiffArgs = samePatch
419
+ ? ['diff', prior.mergeBase, mergeBase, '--', ...decision.touchedFiles]
420
+ : ['diff', prior.head, headSha, '--', ...decision.touchedFiles]
421
+ const fixDiff = git(fixDiffArgs)
422
+ const symbols = changedSymbols(fixDiff)
423
+ const scan = scanDiff(fixDiff)
424
+ return {
425
+ ...result,
426
+ fixDiffCommand: `git ${fixDiffArgs.join(' ')}`,
427
+ fixDiff: fixDiff.length > MAX_FIX_DIFF_CHARS ? null : fixDiff,
428
+ sweepRecheck: sweepRecheck(prior, decision.touchedFiles),
429
+ changedSymbols: symbols,
430
+ callSites: callSites([...symbols.names, ...symbols.anchors], decision.carriedFiles, headSha),
431
+ fixScan: { findings: scan.findings, leads: scan.leads },
432
+ }
433
+ }
434
+
435
+ // The result file a skip writes in place of a review: the previous approval, carried to this
436
+ // HEAD. It ran no checks of its own, found nothing new, and copies the coverage it carries.
437
+ export function skipRecord(prior, scope) {
438
+ if (scope.tier !== 'skip') throw new RereviewScopeError(`tier is ${scope.tier}, not skip: spawn the reviewer`)
439
+ return {
440
+ version: prior.version ?? 1,
441
+ ...(prior.unit === undefined ? {} : { unit: prior.unit }),
442
+ round: scope.round,
443
+ fixRound: scope.fixRound,
444
+ head: scope.head,
445
+ mergeBase: scope.mergeBase,
446
+ patchId: scope.patchId,
447
+ patchFingerprint: scope.patchFingerprint,
448
+ tier: 'skip',
449
+ carriedFrom: prior.head,
450
+ fixLinesSinceFull: scope.fixLinesSinceFull,
451
+ oversize: false,
452
+ complete: true,
453
+ passes: prior.passes,
454
+ commands: [],
455
+ sweeps: prior.sweeps ?? [],
456
+ boundaries: prior.boundaries ?? [],
457
+ findings: [],
458
+ }
459
+ }
460
+
461
+ // Lines in the carried files that use a changed name, capped so a common name cannot flood it.
462
+ function callSites(terms, files, rev) {
463
+ const sites = []
464
+ let truncated = false
465
+ if (files.length === 0) return { sites, truncated }
466
+ for (const term of terms) {
467
+ const word = /^[A-Za-z_$][\w$]*$/.test(term)
468
+ let out = ''
469
+ try {
470
+ out = git(['grep', '-n', '-F', ...(word ? ['-w'] : []), '-e', term, rev, '--', ...files])
471
+ } catch { continue } // git grep exits 1 on no match
472
+ for (const line of lines(out)) {
473
+ const m = line.startsWith(`${rev}:`) ? line.slice(rev.length + 1).match(/^([^:]+):(\d+):(.*)$/) : null
474
+ if (!m) continue
475
+ if (sites.length >= MAX_CALL_SITES) { truncated = true; break }
476
+ sites.push({ term, file: m[1], line: Number(m[2]), text: m[3].trim().slice(0, 200) })
477
+ }
478
+ }
479
+ return { sites, truncated }
480
+ }
481
+
482
+ if (isMainModule(import.meta.url)) {
483
+ try {
484
+ const opts = parseCliArgs(process.argv.slice(2))
485
+ if (opts.help) {
486
+ console.log(USAGE)
487
+ } else {
488
+ let prior
489
+ try { prior = JSON.parse(fs.readFileSync(opts.prior, 'utf8')) } catch (error) {
490
+ throw new RereviewScopeError(`cannot read previous result ${opts.prior}: ${error.message}`)
491
+ }
492
+ const scope = rereviewScope({ prior, base: opts.base, head: opts.head })
493
+ if (opts.writeSkip && scope.tier === 'skip') {
494
+ fs.writeFileSync(opts.writeSkip, `${JSON.stringify(skipRecord(prior, scope), null, 2)}\n`)
495
+ scope.skipRecord = opts.writeSkip
496
+ }
497
+ console.log(JSON.stringify(scope, null, 2))
498
+ }
499
+ } catch (error) {
500
+ console.error(`rereview-scope: ${error.message}`)
501
+ process.exitCode = 2
502
+ }
503
+ }