@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,563 @@
1
+ #!/usr/bin/env python3
2
+ """Validate a compliance checklist Markdown file against the checklist schema.
3
+
4
+ Usage:
5
+ python3 validate_checklist.py <checklist.md> [--source <converted-md>]
6
+
7
+ Without --source, structural checks plus a flattening-detector warning run.
8
+
9
+ With --source <converted-md>, three additional semantic checks run as warnings:
10
+ 1. Source citations: each item's `Source:` field must have at least
11
+ one anchor (digit-bearing token) that appears in the source markdown.
12
+ 2. Modal verbs: each Requirement should contain mandatory language
13
+ (must / shall / required / prohibited / mandatory).
14
+ 3. Verification independence: Verification steps should not be a
15
+ near-paraphrase of the Requirement (Jaccard overlap > 0.5).
16
+
17
+ Always-on flattening detectors (source-native scheme):
18
+ - Marker-based: warns when a top-level Verification bullet contains
19
+ lettered or roman enumerator markers in prose (e.g. "(a)…(b)…(c)")
20
+ with no nested checkboxes — the agent likely flattened source
21
+ sub-bullets that should have been preserved as nested checkboxes
22
+ for auditor traceability.
23
+ - Comma-list: warns when a top-level Verification bullet is long
24
+ (>40 words) and contains many list joiners (4+ commas/semicolons)
25
+ with no nested children. Catches the case where the agent
26
+ paraphrased multiple source provisions into a comma-separated
27
+ summary, dropping the enumerator markers along the way.
28
+
29
+ Exit code 0 = valid. Non-zero = errors found (printed to stderr).
30
+ Warnings never cause non-zero exit.
31
+ """
32
+
33
+ import argparse
34
+ import re
35
+ import sys
36
+ import os
37
+
38
+ REQUIRED_METADATA = {"name", "regulation", "version", "scope", "date"}
39
+ REQUIRED_ITEM_FIELDS = {"Requirement", "Source", "Severity", "Verification", "Evidence"}
40
+
41
+ # Scheme-dependent rules. id_scheme metadata field selects between them;
42
+ # default is "cat".
43
+ SCHEMES = {
44
+ "cat": {
45
+ "cat_re": re.compile(r"^##\s+(CAT-\d{2}):\s+.+"),
46
+ "item_re": re.compile(r"^###\s+(CAT-\d{2}-\d{3}):\s+.+"),
47
+ "severities": ("critical", "major", "minor"),
48
+ "cat_hint": "## CAT-XX: Title",
49
+ "item_hint": "### CAT-XX-NNN: Title",
50
+ },
51
+ "source-native": {
52
+ # Category: uppercase token (letters/digits), e.g. AACQ, ATPA, PCIDSS.
53
+ "cat_re": re.compile(r"^##\s+([A-Z][A-Z0-9]*):\s+.+"),
54
+ # Item: <CAT>.<segment>(.<segment>)+ — preserves source punctuation.
55
+ "item_re": re.compile(
56
+ r"^###\s+([A-Z][A-Z0-9]*\.[A-Za-z0-9]+(?:\.[A-Za-z0-9]+)+):\s+.+"
57
+ ),
58
+ "severities": ("mandatory", "recommended"),
59
+ "cat_hint": "## <UPPERCASE-TOKEN>: Title",
60
+ "item_hint": "### <CAT>.<seg>.<seg>: Title",
61
+ },
62
+ }
63
+
64
+ YAML_BLOCK_RE = re.compile(r"^```yaml\s*$")
65
+ YAML_END_RE = re.compile(r"^```\s*$")
66
+ DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
67
+
68
+
69
+ def category_prefix(item_id: str, scheme: str) -> str:
70
+ """Return the category-ID prefix of an item ID under the given scheme."""
71
+ if scheme == "cat":
72
+ return item_id[:6] # 'CAT-01-001' -> 'CAT-01'
73
+ # source-native: everything before the first dot
74
+ return item_id.split(".", 1)[0]
75
+
76
+ MANDATORY_RE = re.compile(
77
+ r"\b(must|shall|required|requires|require|prohibited|prohibit|mandatory|"
78
+ r"obligated|forbidden|cannot|shall not|may not)\b",
79
+ re.IGNORECASE,
80
+ )
81
+ # Hedges that indicate a non-binding obligation. Present without an
82
+ # overriding mandatory anchor → likely the agent pulled in "should"/"may"
83
+ # guidance and treated it as a requirement.
84
+ WEAK_RE = re.compile(
85
+ r"\b(should|may|encouraged|recommended|best practice|where possible|"
86
+ r"as appropriate|if practicable|where practicable)\b",
87
+ re.IGNORECASE,
88
+ )
89
+ # Anchor token = a substring containing at least one digit, ≥2 chars.
90
+ # Catches: 13(1)(a), 2015/849, 615, 5.2, 76E, AACQ.C2.1.
91
+ ANCHOR_RE = re.compile(r"[\w./()\-]*\d[\w./()\-]*")
92
+ TOKEN_RE = re.compile(r"\b\w+\b")
93
+ STOPWORDS = {
94
+ "the", "a", "an", "of", "to", "and", "or", "in", "on", "for", "with",
95
+ "be", "is", "are", "as", "at", "by", "must", "shall", "all", "any",
96
+ "each", "from", "that", "this", "their", "its", "such", "where", "when",
97
+ "before", "after", "into", "out", "if", "not", "no", "than", "then",
98
+ "have", "has", "been", "being", "must", "may",
99
+ }
100
+ JACCARD_THRESHOLD = 0.5
101
+ JACCARD_MIN_TOKENS = 4 # avoid false positives on tiny items
102
+
103
+ # Flattening detection (source-native only). A top-level Verification
104
+ # bullet that contains 2+ parenthesized lowercase letters or 2+ roman
105
+ # numerals in its text — and has no nested checkboxes under it — is
106
+ # almost certainly a flattened source list (e.g. "Acquirer (a) collects
107
+ # X, (b) verifies Y, (c) reports Z" should have been three nested
108
+ # checkboxes). One match is tolerated (often a citation like section 13(1)(a)).
109
+ LETTER_ENUM_RE = re.compile(r"\([a-z]\)")
110
+ ROMAN_ENUM_RE = re.compile(r"\([ivx]{1,4}\)")
111
+ CHECKBOX_LINE_RE = re.compile(r"^(\s*)-\s*\[[ xX]\]\s*(.+)$")
112
+ FIELD_LABEL_LINE_RE = re.compile(r"^-?\s*\*\*[A-Z][\w\s/-]*:\*\*")
113
+
114
+
115
+ def verification_flattening_warnings(
116
+ raw_lines: list[str],
117
+ item_re: re.Pattern,
118
+ ) -> list[str]:
119
+ """Detect Verification bullets that flatten source sub-bullets into prose.
120
+
121
+ Walks the raw file, tracking which item we're inside and whether we're
122
+ inside that item's Verification field. For each item, collects the
123
+ indentation + text of every checkbox bullet, then flags top-level
124
+ bullets (minimum indent within the item's Verification block) that
125
+ have no children but contain 2+ lettered/roman enumerator markers in
126
+ their text — the textbook flattening pattern.
127
+ """
128
+ warnings: list[str] = []
129
+ # item_id -> list of (indent, text)
130
+ blocks: dict[str, list[tuple[int, str]]] = {}
131
+ current_item: str | None = None
132
+ in_verif = False
133
+
134
+ for line in raw_lines:
135
+ stripped = line.strip()
136
+ m = item_re.match(stripped)
137
+ if m:
138
+ current_item = m.group(1)
139
+ blocks.setdefault(current_item, [])
140
+ in_verif = False
141
+ continue
142
+ if not current_item:
143
+ continue
144
+ # Verification field start
145
+ if stripped.startswith("**Verification:**") or stripped.startswith(
146
+ "- **Verification:**"
147
+ ):
148
+ in_verif = True
149
+ continue
150
+ if not in_verif:
151
+ continue
152
+ # Field-label line that is NOT a checkbox ends the Verification block
153
+ cb_match = CHECKBOX_LINE_RE.match(line.rstrip())
154
+ if not cb_match:
155
+ if FIELD_LABEL_LINE_RE.match(stripped) and not stripped.startswith(
156
+ "- [ ]"
157
+ ) and not stripped.startswith("- [x]"):
158
+ in_verif = False
159
+ continue
160
+ indent = len(cb_match.group(1))
161
+ text = cb_match.group(2)
162
+ blocks[current_item].append((indent, text))
163
+
164
+ for item_id, bullets in blocks.items():
165
+ if not bullets:
166
+ continue
167
+ unprefixed = sum(1 for _, text in bullets if not re.match(r"^\*\*\([^)]+\)\*\*", text))
168
+ if unprefixed:
169
+ warnings.append(
170
+ f"{item_id}: {unprefixed} Verification checkbox(es) lack a bold source prefix "
171
+ f"like **(1)** / **(a)** / **(i)** — source-native steps must name the "
172
+ f"source control item they audit (see checklist-schema.md)."
173
+ )
174
+ min_indent = min(b[0] for b in bullets)
175
+ for idx, (indent, text) in enumerate(bullets):
176
+ if indent != min_indent:
177
+ continue
178
+ has_nested = idx + 1 < len(bullets) and bullets[idx + 1][0] > indent
179
+ if has_nested:
180
+ continue
181
+ letter_hits = len(LETTER_ENUM_RE.findall(text))
182
+ roman_hits = len(ROMAN_ENUM_RE.findall(text))
183
+ if letter_hits >= 2 or roman_hits >= 2:
184
+ kind = "lettered" if letter_hits >= 2 else "roman"
185
+ warnings.append(
186
+ f"{item_id}: Verification bullet contains {kind} enumerator "
187
+ f"markers in prose with no nested checkboxes — likely "
188
+ f"flattened source sub-bullets. Preserve source nesting depth "
189
+ f"(see checklist-schema.md 'Verification step prefixes')."
190
+ )
191
+ continue
192
+ # Comma-list flattening: long bullet packed with joiners but no
193
+ # children. Typically the agent paraphrased multiple source
194
+ # provisions into a single summary and stripped the markers.
195
+ # Strip the bold prefix (e.g. "**(1)**") so it doesn't inflate
196
+ # the word count for short, prefix-heavy bullets.
197
+ stripped_text = re.sub(r"^\*\*\([^)]*\)\*\*\s*", "", text)
198
+ words = stripped_text.split()
199
+ wc = len(words)
200
+ joiner_count = stripped_text.count(",") + stripped_text.count(";")
201
+ if wc > 40 and joiner_count >= 4:
202
+ warnings.append(
203
+ f"{item_id}: Verification bullet is {wc} words with "
204
+ f"{joiner_count} comma/semicolon joiners and no nested "
205
+ f"checkboxes — possibly multiple source provisions "
206
+ f"collapsed into a single summary. Compare against source "
207
+ f"and split if each clause is a discrete obligation."
208
+ )
209
+ return warnings
210
+
211
+
212
+ def parse_yaml_block(lines: list[str]) -> tuple[dict[str, str], dict[str, int], list[str]]:
213
+ """Extract key-value pairs and summary block from the first YAML fenced block."""
214
+ errors = []
215
+ meta: dict[str, str] = {}
216
+ summary: dict[str, int] = {}
217
+ in_yaml = False
218
+ in_summary = False
219
+ found = False
220
+
221
+ for line in lines:
222
+ stripped = line.strip()
223
+ if not in_yaml and YAML_BLOCK_RE.match(stripped):
224
+ in_yaml = True
225
+ found = True
226
+ continue
227
+ if in_yaml:
228
+ if YAML_END_RE.match(stripped):
229
+ break
230
+ # Detect summary block start
231
+ if stripped == "summary:":
232
+ in_summary = True
233
+ continue
234
+ # Parse summary sub-fields (indented)
235
+ if in_summary:
236
+ sm = re.match(r'^(\w+):\s*(\d+)\s*$', stripped)
237
+ if sm:
238
+ summary[sm.group(1)] = int(sm.group(2))
239
+ continue
240
+ else:
241
+ in_summary = False # end of summary block
242
+ # Simple key: "value" or key: value parsing
243
+ m = re.match(r'^(\w+):\s*"?(.+?)"?\s*$', stripped)
244
+ if m:
245
+ meta[m.group(1)] = m.group(2)
246
+
247
+ if not found:
248
+ errors.append("Missing YAML metadata block (```yaml ... ```)")
249
+ return meta, summary, errors
250
+
251
+
252
+ def tokenize(text: str) -> set[str]:
253
+ """Lowercase content tokens, stopwords removed, length >= 3."""
254
+ return {
255
+ w.lower()
256
+ for w in TOKEN_RE.findall(text)
257
+ if len(w) >= 3 and w.lower() not in STOPWORDS
258
+ }
259
+
260
+
261
+ def jaccard(a: set[str], b: set[str]) -> float:
262
+ if not a and not b:
263
+ return 0.0
264
+ return len(a & b) / len(a | b)
265
+
266
+
267
+ def fuzzy_present(token: str, haystack_lower: str) -> bool:
268
+ """Token appears in the haystack as a whole reference, ignoring whitespace.
269
+
270
+ "2(1)(a)" matches "section 2 (1)(a)" but "6" does not match "2026" and
271
+ "1" does not match "2.1" or "10": a leading digit may not follow a digit
272
+ or dot, and a trailing digit may not be followed by one.
273
+ """
274
+ tok = re.sub(r"\s+", "", token.lower()).strip(".,;:")
275
+ if len(re.sub(r"[^a-z0-9]", "", tok)) < 2 and not tok.isdigit():
276
+ return False
277
+ hay = re.sub(r"\s+", "", haystack_lower)
278
+ lead = r"(?<![\d.])" if tok[:1].isdigit() else r"(?<![a-z0-9])"
279
+ tail = r"(?![\d])" if tok[-1:].isdigit() else r"(?![a-z0-9])"
280
+ return re.search(lead + re.escape(tok) + tail, hay) is not None
281
+
282
+
283
+ def validate(filepath: str, source_path: str | None = None) -> tuple[list[str], list[str]]:
284
+ """Return (errors, warnings)."""
285
+ errors: list[str] = []
286
+ warnings: list[str] = []
287
+
288
+ if not os.path.isfile(filepath):
289
+ return [f"File not found: {filepath}"], []
290
+
291
+ with open(filepath, "r", encoding="utf-8") as f:
292
+ lines = f.readlines()
293
+
294
+ raw_lines = [l.rstrip("\n") for l in lines]
295
+
296
+ # --- Metadata ---
297
+ meta, summary, meta_errors = parse_yaml_block(raw_lines)
298
+ errors.extend(meta_errors)
299
+
300
+ for field in REQUIRED_METADATA:
301
+ if field not in meta:
302
+ errors.append(f"Missing required metadata field: {field}")
303
+
304
+ if "date" in meta and not DATE_RE.match(meta["date"]):
305
+ errors.append(f"Invalid date format: '{meta['date']}' (expected YYYY-MM-DD)")
306
+
307
+ # Resolve id_scheme; default = cat. Unknown values are an error.
308
+ scheme_name = meta.get("id_scheme", "cat")
309
+ if scheme_name not in SCHEMES:
310
+ errors.append(
311
+ f"Invalid id_scheme: '{scheme_name}' (must be 'cat' or 'source-native')"
312
+ )
313
+ scheme_name = "cat"
314
+ scheme = SCHEMES[scheme_name]
315
+ cat_re = scheme["cat_re"]
316
+ item_re = scheme["item_re"]
317
+ valid_severities = set(scheme["severities"])
318
+ summary_count_fields = ("categories", "total_items", *scheme["severities"])
319
+
320
+ if not summary:
321
+ errors.append(
322
+ "Missing required metadata field: summary "
323
+ f"({', '.join(summary_count_fields)})"
324
+ )
325
+ else:
326
+ for sf in summary_count_fields:
327
+ if sf not in summary:
328
+ errors.append(f"Missing summary field: {sf}")
329
+
330
+ # Check extends target exists
331
+ if "extends" in meta:
332
+ base_path = meta["extends"]
333
+ # Resolve relative to the checklist file's directory
334
+ checklist_dir = os.path.dirname(os.path.abspath(filepath))
335
+ resolved = os.path.normpath(os.path.join(checklist_dir, base_path))
336
+ if not os.path.isfile(resolved):
337
+ errors.append(f"extends target not found: {base_path} (resolved: {resolved})")
338
+
339
+ # --- Categories and Items ---
340
+ categories: set[str] = set()
341
+ item_ids: list[str] = []
342
+ current_cat: str | None = None
343
+ current_item_id: str | None = None
344
+ item_fields_found: dict[str, set[str]] = {} # item_id -> set of field names
345
+ # Per-item captured text for semantic checks
346
+ item_text: dict[str, dict[str, list[str]]] = {}
347
+ current_field: str | None = None # field currently being captured (multiline)
348
+ verification_checkboxes: dict[str, int] = {}
349
+
350
+ field_label_re = re.compile(r"^-\s+\*\*([\w\s\-]+?):\*\*\s*(.*)$")
351
+
352
+ for line_num, line in enumerate(raw_lines, 1):
353
+ stripped = line.strip()
354
+
355
+ # Category heading
356
+ cat_match = cat_re.match(stripped)
357
+ if cat_match:
358
+ current_cat = cat_match.group(1)
359
+ categories.add(current_cat)
360
+ current_field = None
361
+ continue
362
+
363
+ # Item heading
364
+ item_match = item_re.match(stripped)
365
+ if item_match:
366
+ current_item_id = item_match.group(1)
367
+ item_cat = category_prefix(current_item_id, scheme_name)
368
+
369
+ if item_cat not in categories:
370
+ errors.append(
371
+ f"Line {line_num}: Item {current_item_id} belongs to "
372
+ f"undeclared category {item_cat}"
373
+ )
374
+
375
+ if current_item_id in item_fields_found:
376
+ errors.append(f"Line {line_num}: Duplicate item ID {current_item_id}")
377
+ else:
378
+ item_fields_found[current_item_id] = set()
379
+ item_text[current_item_id] = {
380
+ "Requirement": [], "Source": [], "Verification": [],
381
+ "Evidence": [], "Severity": [],
382
+ }
383
+ item_ids.append(current_item_id)
384
+ current_field = None
385
+ continue
386
+
387
+ # Detect item fields (bold field labels — including multi-word
388
+ # optional fields like "Risk Domain", "Risk Sub-Domain")
389
+ if current_item_id:
390
+ field_match = field_label_re.match(stripped)
391
+ if field_match:
392
+ field_name = field_match.group(1).strip()
393
+ rest = field_match.group(2)
394
+ item_fields_found[current_item_id].add(field_name)
395
+ current_field = field_name if field_name in item_text[current_item_id] else None
396
+ if current_field and rest:
397
+ item_text[current_item_id][current_field].append(rest)
398
+
399
+ # Validate severity value
400
+ if field_name == "Severity":
401
+ sev_val = re.sub(r"[^a-z]", "", rest.lower())
402
+ if sev_val not in valid_severities:
403
+ errors.append(
404
+ f"Line {line_num}: Invalid severity '{sev_val}' "
405
+ f"in item {current_item_id}. "
406
+ f"Must be one of: {', '.join(sorted(valid_severities))}"
407
+ )
408
+ continue
409
+
410
+ # Continuation of a multi-line field (sub-bullets, wrapped text)
411
+ if current_field == "Verification" and re.match(r"^[-*]\s*\[[ xX]\]", stripped):
412
+ verification_checkboxes[current_item_id] = verification_checkboxes.get(current_item_id, 0) + 1
413
+ if current_field and current_item_id and stripped:
414
+ # Strip leading list markers / checkbox so token comparison
415
+ # works on the prose only.
416
+ clean = re.sub(r"^[-*]\s*\[[ xX]\]\s*", "", stripped)
417
+ clean = re.sub(r"^[-*]\s+", "", clean)
418
+ item_text[current_item_id][current_field].append(clean)
419
+
420
+ # Check required fields per item
421
+ for item_id, fields in item_fields_found.items():
422
+ missing = REQUIRED_ITEM_FIELDS - fields
423
+ if missing:
424
+ errors.append(
425
+ f"Item {item_id}: Missing required fields: {', '.join(sorted(missing))}"
426
+ )
427
+
428
+ # Warn if no categories or items found
429
+ if not categories:
430
+ errors.append(f"No categories found (expected '{scheme['cat_hint']}' headings)")
431
+ if not item_ids:
432
+ errors.append(f"No checklist items found (expected '{scheme['item_hint']}' headings)")
433
+
434
+ # Cross-validate summary counts against actual content
435
+ if summary:
436
+ sev_counts: dict[str, int] = {s: 0 for s in scheme["severities"]}
437
+ for item_id, fields in item_fields_found.items():
438
+ in_item = False
439
+ for line in raw_lines:
440
+ s = line.strip()
441
+ if item_re.match(s) and item_id in s:
442
+ in_item = True
443
+ continue
444
+ if in_item and item_re.match(s):
445
+ break
446
+ if in_item and "**Severity:**" in s:
447
+ val = s.split("**Severity:**")[-1].strip().lower()
448
+ val = re.sub(r"[^a-z]", "", val)
449
+ if val in sev_counts:
450
+ sev_counts[val] += 1
451
+ break
452
+
453
+ if summary.get("categories", 0) != len(categories):
454
+ errors.append(f"Summary mismatch: categories={summary['categories']} but found {len(categories)}")
455
+ if summary.get("total_items", 0) != len(item_ids):
456
+ errors.append(f"Summary mismatch: total_items={summary['total_items']} but found {len(item_ids)}")
457
+ for sev in scheme["severities"]:
458
+ if summary.get(sev, 0) != sev_counts[sev]:
459
+ errors.append(f"Summary mismatch: {sev}={summary.get(sev, 0)} but found {sev_counts[sev]}")
460
+
461
+ # Required fields must carry content, and Verification needs a checkbox.
462
+ for item_id in item_ids:
463
+ for field in ("Requirement", "Source", "Verification", "Evidence"):
464
+ if field in item_fields_found.get(item_id, set()) and not "".join(item_text[item_id][field]).strip():
465
+ errors.append(f"Item {item_id}: field {field} is empty")
466
+ if "Verification" in item_fields_found.get(item_id, set()) and not verification_checkboxes.get(item_id):
467
+ errors.append(f"Item {item_id}: Verification has no '- [ ]' steps")
468
+
469
+ # --- Semantic checks (warnings only) ---
470
+ regulation_anchors = set(ANCHOR_RE.findall(meta.get("regulation", "")))
471
+ source_text_lower: str | None = None
472
+ if source_path:
473
+ if not os.path.isfile(source_path):
474
+ warnings.append(f"--source file not found: {source_path}")
475
+ else:
476
+ with open(source_path, "r", encoding="utf-8") as sf:
477
+ source_text_lower = sf.read().lower()
478
+
479
+ for item_id in item_ids:
480
+ fields = item_text.get(item_id, {})
481
+ req = " ".join(fields.get("Requirement", [])).strip()
482
+ src = " ".join(fields.get("Source", [])).strip()
483
+ verif = " ".join(fields.get("Verification", [])).strip()
484
+ sev = " ".join(fields.get("Severity", [])).strip().lower()
485
+ sev = re.sub(r"[^a-z]", "", sev)
486
+
487
+ # Weak-modal check: hedge present, mandatory anchor absent.
488
+ # Imperative-form requirements ("Collect…", "Verify…") pass.
489
+ # Skip for items explicitly classified as recommended — by
490
+ # definition they aren't binding obligations.
491
+ is_recommended = sev == "recommended"
492
+ if not is_recommended and req and WEAK_RE.search(req) and not MANDATORY_RE.search(req):
493
+ warnings.append(
494
+ f"{item_id}: Requirement uses non-binding language "
495
+ f"(should/may/recommended) with no must/shall anchor — "
496
+ f"verify this is actually mandatory in the source"
497
+ )
498
+
499
+ # Verification independence
500
+ if req and verif:
501
+ req_tok = tokenize(req)
502
+ verif_tok = tokenize(verif)
503
+ if len(req_tok) >= JACCARD_MIN_TOKENS and len(verif_tok) >= JACCARD_MIN_TOKENS:
504
+ score = jaccard(req_tok, verif_tok)
505
+ if score > JACCARD_THRESHOLD:
506
+ warnings.append(
507
+ f"{item_id}: Verification overlaps Requirement "
508
+ f"(Jaccard={score:.2f}) — verification should list "
509
+ f"observable steps, not paraphrase the requirement"
510
+ )
511
+
512
+ # Citation existence. Anchors that are only the regulation's own
513
+ # number (Cap. 615, 2015/849) prove nothing about the clause.
514
+ if source_text_lower is not None and src:
515
+ anchors = [a for a in ANCHOR_RE.findall(src) if a not in regulation_anchors]
516
+ if not anchors:
517
+ warnings.append(
518
+ f"{item_id}: Source cites no clause (only the regulation, or no number) — "
519
+ f"add the section/article reference"
520
+ )
521
+ else:
522
+ if not any(fuzzy_present(a, source_text_lower) for a in anchors):
523
+ preview = ", ".join(anchors[:3])
524
+ warnings.append(
525
+ f"{item_id}: Source citation not found in source markdown "
526
+ f"(anchors checked: {preview})"
527
+ )
528
+
529
+ # Flattening detector — only meaningful for source-native, where
530
+ # nested numbering is a structural commitment. cat scheme uses a
531
+ # synthetic ID that doesn't promise to mirror source bullets.
532
+ if scheme_name == "source-native":
533
+ warnings.extend(verification_flattening_warnings(raw_lines, item_re))
534
+
535
+ return errors, warnings
536
+
537
+
538
+ def main() -> None:
539
+ p = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])
540
+ p.add_argument("filepath", help="Path to checklist Markdown file")
541
+ p.add_argument(
542
+ "--source",
543
+ help="Optional path to converted source Markdown for citation, "
544
+ "modal-verb, and verification-independence warnings",
545
+ )
546
+ args = p.parse_args()
547
+
548
+ errors, warnings = validate(args.filepath, args.source)
549
+
550
+ for w in warnings:
551
+ print(f" ⚠️ {w}", file=sys.stderr)
552
+
553
+ if errors:
554
+ print(f"❌ Validation failed for {args.filepath}:", file=sys.stderr)
555
+ for err in errors:
556
+ print(f" • {err}", file=sys.stderr)
557
+ sys.exit(1)
558
+ print(f"✅ {args.filepath} is valid.")
559
+ sys.exit(0)
560
+
561
+
562
+ if __name__ == "__main__":
563
+ main()