@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,674 @@
1
+ #!/usr/bin/env node
2
+ // Coverage Ledger reference tool for the ensure-coverage skill.
3
+ //
4
+ // node coverage-ledger.mjs aggregate # build the computed coverage-index
5
+ // node coverage-ledger.mjs validate # run reconciliation checks, exit non-zero on errors
6
+ // node coverage-ledger.mjs report # render a human-readable index + ADR matrix view
7
+ //
8
+ // It is framework-agnostic: it consumes a generated surface inventory (see
9
+ // references/breadth/inventory-contract.md) plus the curated per-requirement
10
+ // `*.coverage.yml` tree, and resolves evidence from `@covers` annotations in
11
+ // tests. Surface DISCOVERY is repo-specific and is NOT done here — supply the
12
+ // inventory via your own adapter (a reference Next.js one ships in adapters/).
13
+ //
14
+ // Curated files may be .yml/.yaml (needs `js-yaml`) or .json (zero-dep).
15
+
16
+ import fs from 'node:fs'
17
+ import path from 'node:path'
18
+ import process from 'node:process'
19
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
20
+
21
+ // ---------- config ----------
22
+
23
+ const DEFAULTS = {
24
+ inventory: 'docs/tests/_generated/surface-inventory.json',
25
+ coverageDir: 'docs/tests',
26
+ testRoots: ['.'],
27
+ indexOut: 'docs/tests/_generated/coverage-index.json',
28
+ reportOut: 'docs/tests/_generated/coverage-index.md',
29
+ // Optional acceptance-gate inputs. Left empty -> gate is skipped with a notice.
30
+ requirementGlobs: {}, // e.g. { adr: 'docs/adr', prd: 'docs/prd' }
31
+ acceptedMarker: /\bstatus\b[\s*:_-]{0,6}accepted/i, // matches `status: accepted` and `**Status:** accepted`
32
+ // A statically-adequate but un-attested test lands at `Unverified`. Doctrine
33
+ // makes that a BLOCKING state (a yellow that blocks the verdict until a human attests
34
+ // via `verified: true`). Set false to phase in (downgrade Unverified to warn).
35
+ unverifiedBlocks: false,
36
+ }
37
+
38
+ const IGNORE_DIRS = new Set(['node_modules', '.git', '.next', 'dist', 'build', 'coverage'])
39
+ const TEST_RE = /\.(test|spec)\.(ts|tsx|js|jsx|mjs|cjs)$/
40
+ // Internal interception / first-party mocking that makes a surface LOOK covered
41
+ // while proving only proxy wiring. Playwright route faking plus MSW server/worker
42
+ // setup (MSW handlers for first-party paths are the non-Playwright vector).
43
+ const INTERCEPT_RE = /\broute\.fulfill\b|\bpage\.route\s*\(|\bsetupServer\s*\(|\bsetupWorker\s*\(|from\s+['"]msw['"]/
44
+ // Real-rendered-page evidence: a Presentation invariant must be proven against a
45
+ // browser that actually lays out and paints the page. These markers signal a real
46
+ // browser drive (Playwright). Their ABSENCE on a presentation-level test means the
47
+ // claim rests on the DOM/accessibility tree only — the axis's over-mock.
48
+ const BROWSER_RE = /@playwright\/test|\bplaywright\b|\bpage\.(goto|locator|evaluate|getByRole|getByText|getByLabel|setViewportSize|click|fill|type|press|check)\b|\bboundingBox\b|\btoHaveScreenshot\b/
49
+ // JSDOM / Testing-Library render: a non-painting DOM. Useful as an explicit
50
+ // negative signal for the DOM-only over-mock note.
51
+ const DOMONLY_RE = /\bjsdom\b|@testing-library|environment['"\s:]+jsdom/
52
+
53
+ // ---------- surface baseline contract ----------
54
+ //
55
+ // Every inventory surface carries a minimum required-level FLOOR keyed on its
56
+ // (kind, class). `class` is mechanically derived by the adapter (read/detail/
57
+ // mutation); humans may only RAISE the floor (curated requiredLevels, sensitive)
58
+ // or EXCLUDE a surface (gated below). Internal surfaces carry no floor — they are
59
+ // proven transitively and only dead-surface-warned when nothing reaches them.
60
+ // Presentation axis (third coverage axis — can a human perceive/act on the page,
61
+ // not just does the DOM exist). Every live browser route auto-carries a presentation
62
+ // floor on top of its functional browser-journey floor.
63
+ //
64
+ // This file GRADES presentation levels (does a qualifying real-render test exist,
65
+ // is it non-intercepting, is it attested) — it does NOT render the page. The
66
+ // instruments that actually open a browser and observe these invariants live in
67
+ // the e2e-test skill's presentation sweep; ensure-coverage owns the CONTRACT
68
+ // (e2e-test/references/presentation-sweep.md), not the runner.
69
+ //
70
+ // Levels, spine first:
71
+ // render-health — the page renders without a pageerror / console.error /
72
+ // error boundary / HTTP >=500. The cheapest, most foundational
73
+ // catch (an uncaught TypeError on mount fails here first), so it
74
+ // is the SPINE of the axis.
75
+ // spatial — no unintended horizontal overflow / element overlap.
76
+ // perceivability — contrast / invisible controls; negative: wrong-role/absent.
77
+ // reachability — navigational reachability + actionable affordance cues.
78
+ // temporal — layout shift (first-party hermetic; third-party sandbox lane).
79
+ const PRESENTATION_ROUTE_FLOOR = ['presentation:render-health', 'presentation:spatial', 'presentation:perceivability', 'presentation:reachability', 'presentation:temporal']
80
+ // The condition-matrix floor the presentation instruments run at. Feature-derived
81
+ // escalation adds cells (dark theme, RTL, …); see the Presentation axis section of
82
+ // SKILL.md. Kept here so the floor is one source of truth for the e2e instrument.
83
+ const PRESENTATION_VIEWPORT_FLOOR = [375, 1280]
84
+
85
+ const BASELINE = {
86
+ // browser routes: every live page must be driven (browser-journey floor);
87
+ // class only changes WHAT the journey must additionally assert (durable state
88
+ // for mutation, seeded entity for detail) — enforced via depth refutation.
89
+ // Every route also carries the Presentation floor (see PRESENTATION_ROUTE_FLOOR).
90
+ route: {
91
+ read: ['browser-journey', ...PRESENTATION_ROUTE_FLOOR],
92
+ detail: ['browser-journey', ...PRESENTATION_ROUTE_FLOOR],
93
+ mutation: ['browser-journey', ...PRESENTATION_ROUTE_FLOOR],
94
+ _default: ['browser-journey', ...PRESENTATION_ROUTE_FLOOR],
95
+ },
96
+ // bare API endpoints (no browser route): contract floor; writes also need durable-state.
97
+ api: { read: ['api'], mutation: ['api', 'integration'], _default: ['api'] },
98
+ permission: { _default: ['integration'] },
99
+ integration: { _default: ['integration'] },
100
+ // internal surfaces — no independent baseline obligation.
101
+ table: { _default: [] },
102
+ event: { _default: [] },
103
+ job: { _default: [] },
104
+ }
105
+ const INTERNAL_KINDS = new Set(['table', 'event', 'job'])
106
+
107
+ function baselineFor(kind, cls) {
108
+ const k = BASELINE[kind]
109
+ if (!k) return []
110
+ return k[cls] || k._default || []
111
+ }
112
+
113
+ // `sensitive` (human-declared escalation): credential/admin/settings surfaces
114
+ // add a contract + auth obligation on top of the mechanical floor.
115
+ function sensitiveExtra(kind) {
116
+ if (kind === 'route') return ['api'] // page journey + API contract; auth asserted at depth
117
+ return []
118
+ }
119
+
120
+ function strictest(...levelLists) {
121
+ return [...new Set(levelLists.flat().filter(Boolean))]
122
+ }
123
+
124
+ // Exclusion is gated by adapter-confirmed signals, never by a human reason alone:
125
+ // a reachable write surface can NEVER be excluded below its journey floor.
126
+ function exclusionAllowed(kind, cls, reachability) {
127
+ if (kind === 'route') {
128
+ if (cls === 'read') return { ok: true } // static/content read pages may drop to render-health
129
+ if (reachability === 'blocked' || reachability === 'unreachable') return { ok: true }
130
+ return { ok: false, why: `reachable ${cls} route cannot be excluded (reachability=${reachability || 'unknown'}); a reachable write surface must keep its journey floor` }
131
+ }
132
+ if (kind === 'api') {
133
+ if (cls === 'mutation') return { ok: false, why: 'mutation API cannot be excluded' }
134
+ return { ok: true }
135
+ }
136
+ return { ok: true } // internal kinds are excludable
137
+ }
138
+
139
+ // A required level is "behavior" (not satisfiable by unit/mock alone).
140
+ const BEHAVIOR_LEVELS = new Set([
141
+ 'pg-api', 'api', 'integration', 'browser-journey', 'journey', 'ui-e2e', 'e2e',
142
+ 'no-secret-assertion',
143
+ ])
144
+ // Presentation levels are proven against a REAL rendered page (not the DOM tree).
145
+ // They get a stricter "clean test" rule than ordinary behavior levels: the proving
146
+ // test must drive a real browser (BROWSER_RE); a DOM-only/JSDOM test is Over-mocked.
147
+ // `render-health` is the spine (page renders without pageerror/console.error/error
148
+ // boundary/5xx); spatial, perceivability, reachability, temporal sit on top. These
149
+ // are the GRADED tokens; the e2e-test presentation sweep is the runner that emits
150
+ // pass/fail per (route, level) — see e2e-test/references/presentation-sweep.md.
151
+ const PRESENTATION_LEVELS = new Set([
152
+ 'presentation:render-health',
153
+ 'presentation:spatial',
154
+ 'presentation:perceivability',
155
+ 'presentation:reachability',
156
+ 'presentation:temporal',
157
+ // `presentation:visual` is a graded presentation token like the rest, but it is
158
+ // OPT-IN, not part of the route floor (PRESENTATION_ROUTE_FLOOR above): a surface
159
+ // carries it only by declaring it in its curated requiredLevels. A pixel baseline
160
+ // is a maintenance liability, so which routes earn one is a per-surface breadth
161
+ // call — see e2e-test/references/presentation-sweep.md ("the opt-in level").
162
+ 'presentation:visual',
163
+ // `presentation:fidelity` is the other opt-in token, and the only one that is not
164
+ // SELF-referential: every level above (visual included) takes the implementation
165
+ // as its own authority, so a page built wrong from a right design passes all of
166
+ // them — a pixel baseline shot of the wrong page is green forever. Fidelity asks
167
+ // whether the surface matches the design source it was DERIVED from, so a surface
168
+ // carries it only when its work item cites one (prototype/mockup/layout-fixing
169
+ // doc). Proven by a real-browser spec that drives `design-parity.mjs probe` and
170
+ // asserts via `design-parity.mjs validate --observed` — see
171
+ // references/presentation/axis.md ("presentation:fidelity").
172
+ 'presentation:fidelity',
173
+ ])
174
+
175
+ // Any `presentation:*` level (incl. cell-qualified ones like
176
+ // `presentation:perceivability@dark`) is a presentation level — proven against a
177
+ // real rendered page. Prefix-based so feature-derived escalation can mint new
178
+ // condition cells without enumerating every combination here.
179
+ function isPresentationLevel(level) {
180
+ return typeof level === 'string' && level.startsWith('presentation:')
181
+ }
182
+
183
+ // Feature-derived escalation (Dimension B of the condition matrix). The adapter
184
+ // emits deterministic per-surface `signals`; each signal RAISES the floor by adding
185
+ // cell-qualified presentation levels. Pure + deterministic: same signals → same
186
+ // levels (sorted), so two agents on the same code compute identical obligations.
187
+ // - themeToggle → perceivability must also hold in dark theme
188
+ // - i18n → spatial must also hold under a long locale and RTL
189
+ function presentationEscalation(signals = {}) {
190
+ const out = []
191
+ if (signals.themeToggle) out.push('presentation:perceivability@dark')
192
+ if (signals.i18n) out.push('presentation:spatial@long-locale', 'presentation:spatial@rtl')
193
+ return [...new Set(out)].sort()
194
+ }
195
+
196
+ // Gated removal of an escalated cell (Dimension B exclusion). A cell may be dropped
197
+ // only with a `category` + `reason`; the mechanical base floor (unqualified levels)
198
+ // can NEVER be removed this way, and every removal is recorded for the census.
199
+ // `cellExclusions` is a map: { 'presentation:perceivability@dark': { category, reason } }.
200
+ function applyCellExclusions(levels, cellExclusions = {}) {
201
+ const kept = [], census = [], rejected = []
202
+ for (const lvl of levels) {
203
+ const ex = cellExclusions[lvl]
204
+ if (!ex) { kept.push(lvl); continue }
205
+ if (!lvl.includes('@')) { rejected.push({ level: lvl, why: 'cannot exclude a base (unqualified) floor level' }); kept.push(lvl); continue }
206
+ if (!ex.category || !ex.reason) { rejected.push({ level: lvl, why: 'cell exclusion needs category + reason' }); kept.push(lvl); continue }
207
+ census.push({ level: lvl, category: ex.category, reason: ex.reason })
208
+ }
209
+ return { kept, census, rejected }
210
+ }
211
+
212
+ // Synonyms: a test level satisfies a required level if it intersects this set.
213
+ const SYNONYMS = {
214
+ 'pg-api': ['pg-api', 'integration', 'api', 'db'],
215
+ 'api': ['api', 'pg-api', 'integration'],
216
+ 'integration': ['integration', 'pg-api', 'api', 'db'],
217
+ 'browser-journey': ['browser-journey', 'journey', 'e2e', 'ui-e2e'],
218
+ 'journey': ['journey', 'browser-journey', 'e2e', 'ui-e2e'],
219
+ 'ui-e2e': ['ui-e2e', 'e2e', 'browser-journey', 'journey'],
220
+ 'e2e': ['e2e', 'journey', 'browser-journey', 'ui-e2e'],
221
+ 'unit': ['unit'],
222
+ // `render-health` is a minimal BROWSER reachability/render floor (NOT a behavior
223
+ // level — see BEHAVIOR_LEVELS — and deliberately NOT satisfiable by `api`: a real
224
+ // browser must load the page and render it, not just return HTTP 200). A fuller
225
+ // browser journey also satisfies it. This is the breadth-floor sibling of the
226
+ // presentation spine `presentation:render-health` and of e2e-test's Tier-1
227
+ // (Render-health). `smoke` is kept as a back-compat alias (same floor, old name).
228
+ 'render-health': ['render-health', 'smoke', 'browser-journey', 'journey', 'ui-e2e', 'e2e'],
229
+ 'smoke': ['render-health', 'smoke', 'browser-journey', 'journey', 'ui-e2e', 'e2e'],
230
+ 'no-secret-assertion': ['no-secret-assertion'],
231
+ // Presentation levels are exact-match: a `presentation:spatial` obligation is
232
+ // only satisfied by a test that declares `@level presentation:spatial`. A
233
+ // functional browser-journey does NOT satisfy it (a journey clicks the DOM; it
234
+ // does not assert the page is laid out without overflow).
235
+ 'presentation:spatial': ['presentation:spatial'],
236
+ 'presentation:perceivability': ['presentation:perceivability'],
237
+ 'presentation:reachability': ['presentation:reachability'],
238
+ 'presentation:temporal': ['presentation:temporal'],
239
+ // Opt-in pixel baseline — exact-match like its siblings (a functional journey or
240
+ // any other presentation level does not satisfy it). Only present on a surface
241
+ // whose curated requiredLevels raised it in.
242
+ 'presentation:visual': ['presentation:visual'],
243
+ // Exact-match for the same reason, and one more: `presentation:visual` is the
244
+ // level most likely to be offered as a substitute ("we have a baseline, isn't
245
+ // that the same check?"). It is not — a baseline captured from the built page
246
+ // ratifies whatever shipped, which is precisely the failure fidelity exists to
247
+ // catch. Neither satisfies the other.
248
+ 'presentation:fidelity': ['presentation:fidelity'],
249
+ }
250
+
251
+ // ---------- small fs helpers ----------
252
+
253
+ function* walk(dir) {
254
+ let entries
255
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }) } catch { return }
256
+ for (const e of entries) {
257
+ if (e.name.startsWith('.') && e.name !== '.') continue
258
+ const full = path.join(dir, e.name)
259
+ if (e.isDirectory()) {
260
+ if (IGNORE_DIRS.has(e.name)) continue
261
+ yield* walk(full)
262
+ } else {
263
+ yield full
264
+ }
265
+ }
266
+ }
267
+
268
+ async function loadStructured(file) {
269
+ const raw = fs.readFileSync(file, 'utf8')
270
+ if (file.endsWith('.json')) return JSON.parse(raw)
271
+ let yaml
272
+ try { ({ default: yaml } = await import('js-yaml')) }
273
+ catch { throw new Error(`Reading ${file} needs YAML support. Run \`npm install js-yaml\` in scripts/, or use .json coverage files.`) }
274
+ return yaml.load(raw)
275
+ }
276
+
277
+ // ---------- loaders ----------
278
+
279
+ function loadInventory(cfg) {
280
+ if (!fs.existsSync(cfg.inventory)) {
281
+ throw new Error(`Inventory not found: ${cfg.inventory}. Generate it first (see references/breadth/inventory-contract.md).`)
282
+ }
283
+ const data = JSON.parse(fs.readFileSync(cfg.inventory, 'utf8'))
284
+ const surfaces = new Map() // id -> { kind, class, reachability }
285
+ if (Array.isArray(data.surfaces)) {
286
+ for (const s of data.surfaces) surfaces.set(s.id, { kind: s.kind || 'unknown', class: s.class || null, reachability: s.reachability || null, signals: s.signals || null })
287
+ } else {
288
+ // lenient grouped form: { routes:[...], apis:[...], tables:[...], events:[...] }
289
+ // (no class/reachability; entry surfaces fall back to the _default floor)
290
+ for (const [group, list] of Object.entries(data)) {
291
+ if (!Array.isArray(list)) continue
292
+ const kind = group.replace(/s$/, '')
293
+ for (const id of list) surfaces.set(id, { kind, class: null, reachability: null })
294
+ }
295
+ }
296
+ return surfaces
297
+ }
298
+
299
+ async function loadCurated(cfg) {
300
+ const files = []
301
+ for (const f of walk(cfg.coverageDir)) {
302
+ if (!/\.coverage\.(ya?ml|json)$/.test(f)) continue
303
+ const source = path.basename(path.dirname(f)) // adr | prd | design | ...
304
+ const base = path.basename(f).replace(/\.coverage\.(ya?ml|json)$/, '')
305
+ const id = base.split('-')[0]
306
+ const ref = `${source}:${id}`
307
+ let doc
308
+ try { doc = await loadStructured(f) } catch (e) { throw new Error(`${f}: ${e.message}`) }
309
+ const surfaces = doc?.surfaces || {}
310
+ files.push({ file: f, source, id, ref, criteria: doc?.criteria || null, gapIssue: doc?.gapIssue || null, gapDoc: doc?.gapDoc || null, surfaces })
311
+ }
312
+ return files
313
+ }
314
+
315
+ function scanTests(cfg) {
316
+ const index = new Map() // surfaceId -> [{file, levels:Set, intercepts}]
317
+ for (const root of cfg.testRoots) {
318
+ for (const f of walk(root)) {
319
+ if (!TEST_RE.test(f)) continue
320
+ const text = fs.readFileSync(f, 'utf8')
321
+ const covers = [...text.matchAll(/@covers\s+(\S+)/g)].map((m) => m[1].replace(/^route:/, ''))
322
+ if (covers.length === 0) continue
323
+ const levels = new Set([...text.matchAll(/@level\s+(\S+)/g)].map((m) => m[1]))
324
+ if (levels.size === 0) inferLevels(f).forEach((l) => levels.add(l))
325
+ const intercepts = INTERCEPT_RE.test(text)
326
+ const realBrowser = BROWSER_RE.test(text)
327
+ const domOnly = DOMONLY_RE.test(text)
328
+ for (const id of covers) {
329
+ if (!index.has(id)) index.set(id, [])
330
+ index.get(id).push({ file: f, levels, intercepts, realBrowser, domOnly })
331
+ }
332
+ }
333
+ }
334
+ return index
335
+ }
336
+
337
+ function inferLevels(file) {
338
+ const p = file.replace(/\\/g, '/')
339
+ if (/\/e2e\//.test(p)) return ['e2e']
340
+ if (/\/integration\//.test(p)) return ['integration']
341
+ if (/\/unit\//.test(p)) return ['unit']
342
+ return ['unit']
343
+ }
344
+
345
+ // ---------- aggregation ----------
346
+
347
+ function satisfies(testLevels, required) {
348
+ const syn = SYNONYMS[required] || [required]
349
+ for (const tl of testLevels) if (syn.includes(tl)) return true
350
+ return false
351
+ }
352
+
353
+ function depthStatus(requiredLevels, tests, opts = {}) {
354
+ if (tests.length === 0) return { status: 'Missing', note: 'no test annotated @covers this surface' }
355
+ const required = requiredLevels.length ? requiredLevels : ['unit']
356
+ let unmet = []
357
+ let blockedByInterception = false
358
+ let presentationDomOnly = [] // presentation levels proven without real-render evidence
359
+ for (const rl of required) {
360
+ const proving = tests.filter((t) => satisfies(t.levels, rl))
361
+ if (proving.length === 0) { unmet.push(rl); continue }
362
+ if (isPresentationLevel(rl)) {
363
+ // Presentation invariants must be proven against a real rendered page; a
364
+ // DOM-only / JSDOM test (no real browser drive) is the axis's over-mock.
365
+ const rendered = proving.filter((t) => t.realBrowser && !t.intercepts)
366
+ if (rendered.length === 0) { presentationDomOnly.push(rl); unmet.push(rl) }
367
+ } else if (BEHAVIOR_LEVELS.has(rl)) {
368
+ const clean = proving.filter((t) => !t.intercepts)
369
+ if (clean.length === 0) { blockedByInterception = true; unmet.push(rl) }
370
+ }
371
+ }
372
+ if (blockedByInterception) return { status: 'Over-mocked', note: `behavior level met only by internal interception / first-party mocking (route.fulfill/page.route/msw): ${unmet.join(', ')}` }
373
+ if (presentationDomOnly.length) return { status: 'Over-mocked', note: `presentation level proven without real rendered-page evidence (DOM-only/JSDOM — drive a real browser): ${presentationDomOnly.join(', ')}` }
374
+ if (unmet.length) return { status: 'Wrong Level', note: `required level(s) not proven: ${unmet.join(', ')}` }
375
+ // A self-declared @level can never reach Covered on its own. With reviewer
376
+ // attestation (`verified: true` in the curated file) it promotes; otherwise it
377
+ // lands at Unverified (a warning unless the user sets unverifiedBlocks: true).
378
+ if (opts.attested) return { status: 'Covered', note: 'required level(s) proven by clean tests and marked read (verified)' }
379
+ return { status: 'Unverified', note: 'level satisfied statically but not yet marked read — assertion/execution quality unconfirmed; add `verified: true` to the curated file once the test has been read to promote to Covered' }
380
+ }
381
+
382
+ // Turn a depth status into a finding. Missing/Over-mocked/Wrong Level always
383
+ // fail; Unverified warns by default and blocks only when cfg.unverifiedBlocks is true.
384
+ function emitDepth(findings, cfg, sid, ds) {
385
+ if (ds.status === 'Missing' || ds.status === 'Over-mocked' || ds.status === 'Wrong Level') {
386
+ findings.push({ severity: 'error', kind: ds.status, surface: sid, detail: ds.note })
387
+ } else if (ds.status === 'Unverified') {
388
+ findings.push({ severity: cfg.unverifiedBlocks === true ? 'error' : 'warn', kind: 'Unverified', surface: sid, detail: ds.note })
389
+ }
390
+ }
391
+
392
+ async function build(cfg) {
393
+ const inventory = loadInventory(cfg)
394
+ const curated = await loadCurated(cfg)
395
+ const tests = scanTests(cfg)
396
+
397
+ const index = new Map() // surfaceId -> row
398
+ const findings = []
399
+
400
+ // owned surfaces from curated files
401
+ const owners = new Map() // surfaceId -> { refs, requiredLevels, files, sensitive, verified, exclude }
402
+ for (const cf of curated) {
403
+ if (cf.criteria && !fs.existsSync(cf.criteria)) {
404
+ findings.push({ severity: 'error', kind: 'Stale link', surface: '(criteria)', detail: `${cf.ref} criteria missing: ${cf.criteria}` })
405
+ }
406
+ for (const [sid, meta] of Object.entries(cf.surfaces)) {
407
+ if (!owners.has(sid)) owners.set(sid, { refs: new Set(), requiredLevels: new Set(), files: [], sensitive: false, verified: false, exclude: null, excludeCells: {} })
408
+ const o = owners.get(sid)
409
+ o.refs.add(cf.ref)
410
+ for (const l of meta?.requiredLevels || []) o.requiredLevels.add(l)
411
+ if (meta?.sensitive) o.sensitive = true
412
+ if (meta?.verified) o.verified = true
413
+ if (meta?.exclude) o.exclude = meta.exclude
414
+ if (meta?.excludeCells) Object.assign(o.excludeCells, meta.excludeCells)
415
+ o.files.push(cf.file)
416
+ }
417
+ }
418
+
419
+ // Unrealized: curated surface absent from inventory
420
+ for (const [sid, o] of owners) {
421
+ if (!inventory.has(sid)) {
422
+ index.set(sid, { surface: sid, requirementRefs: [...o.refs], requiredLevels: [...o.requiredLevels], alignment: 'Unrealized requirement', depthStatus: null, evidence: [] })
423
+ findings.push({ severity: 'error', kind: 'Unrealized requirement', surface: sid, detail: `owned by ${[...o.refs].join(', ')} but not in inventory` })
424
+ }
425
+ }
426
+
427
+ // Inventory surfaces. Orphan is no longer a hard error: ownership (traceability
428
+ // to a requirement) is decoupled from the TEST obligation. The baseline floor
429
+ // auto-applies and is graded at depth whether or not a requirement owns it.
430
+ for (const [sid, surf] of inventory) {
431
+ const { kind, class: cls, reachability } = surf
432
+ const o = owners.get(sid)
433
+ const ts = tests.get(sid) || []
434
+
435
+ // Exclusion (human-declared, gated by adapter signals).
436
+ if (o?.exclude) {
437
+ const ex = o.exclude
438
+ const allowed = exclusionAllowed(kind, cls, reachability)
439
+ if (!ex.category || !ex.reason) {
440
+ findings.push({ severity: 'error', kind: 'Exclusion invalid', surface: sid, detail: 'exclude requires both `category` and `reason`' })
441
+ } else if (!allowed.ok) {
442
+ findings.push({ severity: 'error', kind: 'Exclusion rejected', surface: sid, detail: allowed.why })
443
+ } else {
444
+ // `static` keeps a minimal render-health floor (no surface ships with zero
445
+ // test); seed/deprecated/internal drop to manifest-only.
446
+ const residual = ex.category === 'static' ? ['render-health'] : []
447
+ if (residual.length) {
448
+ const ds = depthStatus(residual, ts, { attested: !!o.verified })
449
+ index.set(sid, { surface: sid, kind, class: cls, requirementRefs: [...o.refs].sort(), requiredLevels: residual, alignment: o ? 'Aligned' : 'Orphan surface', depthStatus: ds.status, depthNote: ds.note, evidence: ts.map((t) => t.file) })
450
+ findings.push({ severity: 'warn', kind: 'Excluded', surface: sid, detail: `${ex.category} → render-health floor: ${ex.reason}${ex.gapIssue ? ` (${ex.gapIssue})` : ''}` })
451
+ emitDepth(findings, cfg, sid, ds)
452
+ } else {
453
+ index.set(sid, { surface: sid, kind, class: cls, requirementRefs: [...o.refs].sort(), requiredLevels: [], alignment: 'Excluded', depthStatus: 'Excluded', evidence: ts.map((t) => t.file) })
454
+ findings.push({ severity: 'warn', kind: 'Excluded', surface: sid, detail: `${ex.category}: ${ex.reason}${ex.gapIssue ? ` (${ex.gapIssue})` : ''}` })
455
+ }
456
+ continue
457
+ }
458
+ }
459
+
460
+ // Internal surfaces carry no baseline; warn only when nothing reaches them.
461
+ if (INTERNAL_KINDS.has(kind)) {
462
+ const reached = ts.length > 0
463
+ index.set(sid, { surface: sid, kind, class: cls, requirementRefs: [...(o?.refs || [])].sort(), requiredLevels: [], alignment: o ? 'Aligned' : 'Orphan surface', depthStatus: reached ? 'Reached' : 'Dead', evidence: ts.map((t) => t.file) })
464
+ if (!reached) findings.push({ severity: 'warn', kind: 'Dead surface', surface: sid, detail: `${kind} reached by no test/entry evidence — likely dead or untracked` })
465
+ continue
466
+ }
467
+
468
+ // Entry surfaces: floor = strictest(baseline, curated raise, sensitive
469
+ // escalation, feature-derived presentation cells), minus any gated cell
470
+ // exclusions. The base mechanical floor can never be removed; only escalated
471
+ // (`@`-qualified) cells may be excluded with a category + reason.
472
+ const sensitive = !!o?.sensitive
473
+ const escalation = presentationEscalation(surf.signals || {})
474
+ const fullFloor = strictest(baselineFor(kind, cls), [...(o?.requiredLevels || [])], sensitive ? sensitiveExtra(kind) : [], escalation)
475
+ const { kept: required, census: cellCensus, rejected: cellRejected } = applyCellExclusions(fullFloor, o?.excludeCells || {})
476
+ for (const c of cellCensus) findings.push({ severity: 'warn', kind: 'Cell excluded', surface: sid, detail: `${c.level}: ${c.category} — ${c.reason}` })
477
+ for (const r of cellRejected) findings.push({ severity: 'error', kind: 'Cell exclusion rejected', surface: sid, detail: `${r.level}: ${r.why}` })
478
+ const ds = depthStatus(required, ts, { attested: !!o?.verified })
479
+ index.set(sid, {
480
+ surface: sid, kind, class: cls,
481
+ requirementRefs: [...(o?.refs || [])].sort(),
482
+ requiredLevels: required,
483
+ alignment: o ? 'Aligned' : 'Orphan surface',
484
+ depthStatus: ds.status,
485
+ depthNote: ds.note,
486
+ evidence: ts.map((t) => t.file),
487
+ })
488
+
489
+ // Ownership gap is a WARN (decoupled), and notes the baseline still applies.
490
+ if (!o) findings.push({ severity: 'warn', kind: 'Orphan surface', surface: sid, detail: `${kind} owned by no requirement; baseline ${required.join(' ') || '-'} still enforced` })
491
+
492
+ // Test obligation is the hard gate.
493
+ emitDepth(findings, cfg, sid, ds)
494
+ }
495
+
496
+ // Acceptance gate (optional)
497
+ gateFindings(cfg, curated, findings)
498
+
499
+ return { cfg, index, findings }
500
+ }
501
+
502
+ function gateFindings(cfg, curated, findings) {
503
+ const sources = Object.entries(cfg.requirementGlobs || {})
504
+ if (sources.length === 0) {
505
+ findings.push({ severity: 'info', kind: 'Gate skipped', surface: '-', detail: 'no requirementGlobs configured; acceptance gate not enforced' })
506
+ return
507
+ }
508
+ // An accepted requirement with runtime behavior must own a coverage file that either
509
+ // links its criteria doc or points at a tracked gap (gapIssue / gapDoc). A coverage file
510
+ // with neither is a placeholder, not proof of intent: it satisfies the file-exists check
511
+ // while saying nothing, which is the shape agentier's own ADR gate rejects.
512
+ const byRef = new Map(curated.map((c) => [c.ref, c]))
513
+ for (const [source, dir] of sources) {
514
+ if (!fs.existsSync(dir)) {
515
+ findings.push({ severity: 'error', kind: 'Gate', surface: `${source}:*`, detail: `requirementGlobs.${source} points at ${dir}, which does not exist` })
516
+ continue
517
+ }
518
+ for (const f of walk(dir)) {
519
+ if (!/\.mdx?$/.test(f)) continue
520
+ const text = fs.readFileSync(f, 'utf8')
521
+ if (!cfg.acceptedMarker.test(text)) continue
522
+ const id = path.basename(f).split('-')[0].replace(/\.mdx?$/, '')
523
+ const ref = `${source}:${id}`
524
+ if (/no runtime behavior/i.test(text)) continue
525
+ const cf = byRef.get(ref)
526
+ if (!cf) {
527
+ findings.push({ severity: 'error', kind: 'Gate', surface: ref, detail: `accepted ${ref} has no ${source}/${id}-*.coverage.* file` })
528
+ } else if (!cf.criteria && !cf.gapIssue && !cf.gapDoc) {
529
+ findings.push({ severity: 'error', kind: 'Gate', surface: ref, detail: `accepted ${ref} has a coverage file with no criteria doc and no tracked gap (gapIssue / gapDoc)` })
530
+ }
531
+ }
532
+ }
533
+ }
534
+
535
+ // ---------- outputs ----------
536
+
537
+ function indexToObject(index) {
538
+ const out = {}
539
+ for (const [sid, row] of [...index].sort((a, b) => a[0].localeCompare(b[0]))) {
540
+ const { surface, ...rest } = row
541
+ out[sid] = rest
542
+ }
543
+ return out
544
+ }
545
+
546
+ // Over-mock rate (depth-axis honesty metric). A raw over-mock *count* rises just
547
+ // because the suite grew; a *rate* trends whether the tests that exist are honest.
548
+ // Denominator is surfaces that owe a depth check AND have tests — over-mock is a
549
+ // property of a test that exists but fakes its own internals, so a `Missing`
550
+ // surface (no test at all) is not over-mocked, just absent, and `Excluded`
551
+ // surfaces owe nothing. Numerator is the `Over-mocked` depthStatus the ledger
552
+ // already assigns (behavior level met only by interception, or a presentation
553
+ // level proven DOM-only). Split by axis via the note so a regression points at
554
+ // the right axis. `overMockRate` is 0 when nothing is tested (no honesty to
555
+ // measure), never NaN — a trend consumer can read it unconditionally.
556
+ const DEPTH_GRADED = new Set(['Missing', 'Over-mocked', 'Wrong Level', 'Covered', 'Unverified', 'Partial'])
557
+ function computeMetrics(index) {
558
+ const rows = [...index.values()]
559
+ // Only depth-graded surfaces count — not the `Reached`/`Dead` reachability
560
+ // states (events/jobs), `Excluded`, or `null` (unrealized requirements).
561
+ const graded = rows.filter((r) => DEPTH_GRADED.has(r.depthStatus))
562
+ const tested = graded.filter((r) => r.depthStatus !== 'Missing')
563
+ const overMocked = graded.filter((r) => r.depthStatus === 'Over-mocked')
564
+ const overMockedPresentation = overMocked.filter((r) => /presentation level/i.test(r.depthNote || '')).length
565
+ const overMockedBehavior = overMocked.length - overMockedPresentation
566
+ const rate = tested.length ? overMocked.length / tested.length : 0
567
+ return {
568
+ surfaces: index.size,
569
+ depthGraded: graded.length,
570
+ tested: tested.length,
571
+ overMocked: overMocked.length,
572
+ overMockedBehavior,
573
+ overMockedPresentation,
574
+ overMockRate: Math.round(rate * 1e4) / 1e4,
575
+ overMockRatePct: Math.round(rate * 1000) / 10,
576
+ }
577
+ }
578
+
579
+ const fmtOverMock = (m) => `${m.overMocked}/${m.tested} tested surfaces over-mocked (${m.overMockRatePct}%)`
580
+
581
+ function renderReport(index) {
582
+ const rows = [...index.values()].sort((a, b) => a.surface.localeCompare(b.surface))
583
+ const line = (r) => `| \`${r.surface}\` | ${r.kind || '-'} | ${r.alignment} | ${r.depthStatus || '-'} | ${(r.requirementRefs || []).join(', ') || '-'} | ${(r.requiredLevels || []).join(' ') || '-'} | ${(r.evidence || []).length} |`
584
+ const out = []
585
+ out.push('# Coverage Index (generated — do not hand-edit)\n')
586
+ out.push(`**Over-mock rate:** ${fmtOverMock(computeMetrics(index))} — the share of tested surfaces whose depth level is met only by faking first-party internals (behavior interception or DOM-only presentation). Lower is healthier; the gate requires 0.\n`)
587
+ out.push('| Surface | Kind | Alignment | Depth | Requirements | Required levels | Evidence files |')
588
+ out.push('|---|---|---|---|---|---|---|')
589
+ for (const r of rows) out.push(line(r))
590
+ const adr = rows.filter((r) => (r.requirementRefs || []).some((x) => x.startsWith('adr:')))
591
+ if (adr.length) {
592
+ out.push('\n## ADR Coverage Matrix (view: rows with `adr:` refs)\n')
593
+ out.push('| Surface | Alignment | Depth | ADRs | Required levels |')
594
+ out.push('|---|---|---|---|---|')
595
+ for (const r of adr) out.push(`| \`${r.surface}\` | ${r.alignment} | ${r.depthStatus || '-'} | ${(r.requirementRefs).filter((x) => x.startsWith('adr:')).join(', ')} | ${(r.requiredLevels || []).join(' ') || '-'} |`)
596
+ }
597
+ return out.join('\n') + '\n'
598
+ }
599
+
600
+ // ---------- CLI ----------
601
+
602
+ function parseArgs(argv) {
603
+ const cmd = argv[2]
604
+ const cfg = { ...DEFAULTS }
605
+ const flags = {}
606
+ for (let i = 3; i < argv.length; i++) {
607
+ const a = argv[i]
608
+ if (a === '--strict') flags.strict = true
609
+ else if (a === '--warn-only') flags.warnOnly = true
610
+ else if (a.startsWith('--')) { flags[a.slice(2)] = argv[++i] }
611
+ }
612
+ if (flags.config && fs.existsSync(flags.config)) Object.assign(cfg, JSON.parse(fs.readFileSync(flags.config, 'utf8')))
613
+ if (flags.inventory) cfg.inventory = flags.inventory
614
+ if (flags['coverage-dir']) cfg.coverageDir = flags['coverage-dir']
615
+ if (flags['test-roots']) cfg.testRoots = flags['test-roots'].split(',')
616
+ if (flags.out) cfg.indexOut = cfg.reportOut = flags.out
617
+ if (cfg.acceptedMarker && typeof cfg.acceptedMarker === 'string') cfg.acceptedMarker = new RegExp(cfg.acceptedMarker, 'i')
618
+ return { cmd, cfg, flags }
619
+ }
620
+
621
+ function ensureDir(p) { fs.mkdirSync(path.dirname(p), { recursive: true }) }
622
+
623
+ async function main() {
624
+ const { cmd, cfg, flags } = parseArgs(process.argv)
625
+ if (!['aggregate', 'validate', 'report'].includes(cmd)) {
626
+ console.error('usage: coverage-ledger <aggregate|validate|report> [--config f] [--inventory f] [--coverage-dir d] [--test-roots a,b] [--out f] [--strict] [--warn-only]')
627
+ process.exit(2)
628
+ }
629
+ const { index, findings } = await build(cfg)
630
+
631
+ if (cmd === 'aggregate') {
632
+ ensureDir(cfg.indexOut)
633
+ fs.writeFileSync(cfg.indexOut, JSON.stringify(indexToObject(index), null, 2) + '\n')
634
+ // Emit the metrics as a sibling artifact (not a key in the surface-keyed
635
+ // index, which consumers iterate) so CI / the reviewer can trend the rate over
636
+ // time instead of only gating on zero.
637
+ const metrics = computeMetrics(index)
638
+ const metricsOut = path.join(path.dirname(cfg.indexOut), 'coverage-metrics.json')
639
+ fs.writeFileSync(metricsOut, JSON.stringify(metrics, null, 2) + '\n')
640
+ console.log(`wrote ${cfg.indexOut} (${index.size} surfaces) · ${metricsOut} (${fmtOverMock(metrics)})`)
641
+ return
642
+ }
643
+ if (cmd === 'report') {
644
+ ensureDir(cfg.reportOut)
645
+ fs.writeFileSync(cfg.reportOut, renderReport(index))
646
+ console.log(`wrote ${cfg.reportOut}`)
647
+ return
648
+ }
649
+
650
+ // validate
651
+ const errors = findings.filter((f) => f.severity === 'error' || (flags.strict && f.severity === 'warn'))
652
+ const warns = findings.filter((f) => f.severity === 'warn' && !flags.strict)
653
+ const infos = findings.filter((f) => f.severity === 'info')
654
+ const fmt = (f) => ` [${f.kind}] ${f.surface}: ${f.detail}`
655
+ if (errors.length) { console.log(`\nERRORS (${errors.length}):`); errors.forEach((f) => console.log(fmt(f))) }
656
+ if (warns.length) { console.log(`\nWARNINGS (${warns.length}):`); warns.forEach((f) => console.log(fmt(f))) }
657
+ if (infos.length) infos.forEach((f) => console.log(`\nnote: ${f.detail}`))
658
+ const aligned = [...index.values()].filter((r) => r.alignment === 'Aligned').length
659
+ console.log(`\n${index.size} surfaces · ${aligned} aligned · ${fmtOverMock(computeMetrics(index))} · ${errors.length} errors · ${warns.length} warnings`)
660
+ if (errors.length && !flags.warnOnly) process.exit(1)
661
+ }
662
+
663
+ // Run the CLI only when invoked directly; importing this module (e.g. from tests)
664
+ // must not execute main().
665
+ if (isMainModule(import.meta.url)) {
666
+ main().catch((e) => { console.error(`coverage-ledger: ${e.message}`); process.exit(2) })
667
+ }
668
+
669
+ export {
670
+ build, depthStatus, baselineFor, sensitiveExtra, strictest, satisfies,
671
+ isPresentationLevel, presentationEscalation, applyCellExclusions, computeMetrics,
672
+ BASELINE, SYNONYMS, BEHAVIOR_LEVELS, PRESENTATION_LEVELS,
673
+ PRESENTATION_ROUTE_FLOOR, PRESENTATION_VIEWPORT_FLOOR,
674
+ }