devskill 2.0.7 → 2.0.8

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 (1016) hide show
  1. package/meta.ts +4 -0
  2. package/package.json +1 -1
  3. package/skills/add-educational-comments/LICENSE.md +21 -0
  4. package/skills/add-educational-comments/SKILL.md +128 -0
  5. package/skills/add-educational-comments/SYNC.md +5 -0
  6. package/skills/agent-governance/LICENSE.md +21 -0
  7. package/skills/agent-governance/SKILL.md +569 -0
  8. package/skills/agent-governance/SYNC.md +5 -0
  9. package/skills/agentic-eval/LICENSE.md +21 -0
  10. package/skills/agentic-eval/SKILL.md +189 -0
  11. package/skills/agentic-eval/SYNC.md +5 -0
  12. package/skills/ai-prompt-engineering-safety-review/LICENSE.md +21 -0
  13. package/skills/ai-prompt-engineering-safety-review/SKILL.md +230 -0
  14. package/skills/ai-prompt-engineering-safety-review/SYNC.md +5 -0
  15. package/skills/appinsights-instrumentation/LICENSE.md +21 -0
  16. package/skills/appinsights-instrumentation/LICENSE.txt +21 -0
  17. package/skills/appinsights-instrumentation/SKILL.md +48 -0
  18. package/skills/appinsights-instrumentation/SYNC.md +5 -0
  19. package/skills/appinsights-instrumentation/examples/appinsights.bicep +30 -0
  20. package/skills/appinsights-instrumentation/references/ASPNETCORE.md +29 -0
  21. package/skills/appinsights-instrumentation/references/AUTO.md +13 -0
  22. package/skills/appinsights-instrumentation/references/NODEJS.md +28 -0
  23. package/skills/appinsights-instrumentation/references/PYTHON.md +48 -0
  24. package/skills/appinsights-instrumentation/scripts/appinsights.ps1 +20 -0
  25. package/skills/apple-appstore-reviewer/LICENSE.md +21 -0
  26. package/skills/apple-appstore-reviewer/SKILL.md +305 -0
  27. package/skills/apple-appstore-reviewer/SYNC.md +5 -0
  28. package/skills/arch-linux-triage/LICENSE.md +21 -0
  29. package/skills/arch-linux-triage/SKILL.md +31 -0
  30. package/skills/arch-linux-triage/SYNC.md +5 -0
  31. package/skills/architecture-blueprint-generator/LICENSE.md +21 -0
  32. package/skills/architecture-blueprint-generator/SKILL.md +322 -0
  33. package/skills/architecture-blueprint-generator/SYNC.md +5 -0
  34. package/skills/aspire/LICENSE.md +21 -0
  35. package/skills/aspire/SKILL.md +231 -0
  36. package/skills/aspire/SYNC.md +5 -0
  37. package/skills/aspire/references/architecture.md +341 -0
  38. package/skills/aspire/references/cli-reference.md +307 -0
  39. package/skills/aspire/references/dashboard.md +226 -0
  40. package/skills/aspire/references/deployment.md +237 -0
  41. package/skills/aspire/references/integrations-catalog.md +68 -0
  42. package/skills/aspire/references/mcp-server.md +195 -0
  43. package/skills/aspire/references/polyglot-apis.md +296 -0
  44. package/skills/aspire/references/testing.md +281 -0
  45. package/skills/aspire/references/troubleshooting.md +194 -0
  46. package/skills/aspnet-minimal-api-openapi/LICENSE.md +21 -0
  47. package/skills/aspnet-minimal-api-openapi/SKILL.md +41 -0
  48. package/skills/aspnet-minimal-api-openapi/SYNC.md +5 -0
  49. package/skills/automate-this/LICENSE.md +21 -0
  50. package/skills/automate-this/SKILL.md +244 -0
  51. package/skills/automate-this/SYNC.md +5 -0
  52. package/skills/autoresearch/LICENSE.md +21 -0
  53. package/skills/autoresearch/SKILL.md +275 -0
  54. package/skills/autoresearch/SYNC.md +5 -0
  55. package/skills/aws-cdk-python-setup/LICENSE.md +21 -0
  56. package/skills/aws-cdk-python-setup/SKILL.md +111 -0
  57. package/skills/aws-cdk-python-setup/SYNC.md +5 -0
  58. package/skills/az-cost-optimize/LICENSE.md +21 -0
  59. package/skills/az-cost-optimize/SKILL.md +305 -0
  60. package/skills/az-cost-optimize/SYNC.md +5 -0
  61. package/skills/azure-deployment-preflight/LICENSE.md +21 -0
  62. package/skills/azure-deployment-preflight/SKILL.md +216 -0
  63. package/skills/azure-deployment-preflight/SYNC.md +5 -0
  64. package/skills/azure-deployment-preflight/references/ERROR-HANDLING.md +392 -0
  65. package/skills/azure-deployment-preflight/references/REPORT-TEMPLATE.md +352 -0
  66. package/skills/azure-deployment-preflight/references/VALIDATION-COMMANDS.md +379 -0
  67. package/skills/azure-devops-cli/LICENSE.md +21 -0
  68. package/skills/azure-devops-cli/SKILL.md +94 -0
  69. package/skills/azure-devops-cli/SYNC.md +5 -0
  70. package/skills/azure-devops-cli/references/advanced-usage.md +197 -0
  71. package/skills/azure-devops-cli/references/boards-and-iterations.md +258 -0
  72. package/skills/azure-devops-cli/references/org-and-security.md +469 -0
  73. package/skills/azure-devops-cli/references/pipelines-and-builds.md +245 -0
  74. package/skills/azure-devops-cli/references/repos-and-prs.md +333 -0
  75. package/skills/azure-devops-cli/references/variables-and-agents.md +212 -0
  76. package/skills/azure-devops-cli/references/workflows-and-patterns.md +668 -0
  77. package/skills/azure-pricing/LICENSE.md +21 -0
  78. package/skills/azure-pricing/SKILL.md +189 -0
  79. package/skills/azure-pricing/SYNC.md +5 -0
  80. package/skills/azure-pricing/references/COPILOT-STUDIO-RATES.md +135 -0
  81. package/skills/azure-pricing/references/COST-ESTIMATOR.md +142 -0
  82. package/skills/azure-pricing/references/REGIONS.md +84 -0
  83. package/skills/azure-pricing/references/SERVICE-NAMES.md +106 -0
  84. package/skills/azure-resource-health-diagnose/LICENSE.md +21 -0
  85. package/skills/azure-resource-health-diagnose/SKILL.md +290 -0
  86. package/skills/azure-resource-health-diagnose/SYNC.md +5 -0
  87. package/skills/azure-resource-visualizer/LICENSE.md +21 -0
  88. package/skills/azure-resource-visualizer/LICENSE.txt +21 -0
  89. package/skills/azure-resource-visualizer/SKILL.md +233 -0
  90. package/skills/azure-resource-visualizer/SYNC.md +5 -0
  91. package/skills/azure-resource-visualizer/assets/template-architecture.md +41 -0
  92. package/skills/azure-role-selector/LICENSE.md +21 -0
  93. package/skills/azure-role-selector/LICENSE.txt +21 -0
  94. package/skills/azure-role-selector/SKILL.md +6 -0
  95. package/skills/azure-role-selector/SYNC.md +5 -0
  96. package/skills/azure-static-web-apps/LICENSE.md +21 -0
  97. package/skills/azure-static-web-apps/SKILL.md +315 -0
  98. package/skills/azure-static-web-apps/SYNC.md +5 -0
  99. package/skills/bigquery-pipeline-audit/LICENSE.md +21 -0
  100. package/skills/bigquery-pipeline-audit/SKILL.md +129 -0
  101. package/skills/bigquery-pipeline-audit/SYNC.md +5 -0
  102. package/skills/boost-prompt/LICENSE.md +21 -0
  103. package/skills/boost-prompt/SKILL.md +25 -0
  104. package/skills/boost-prompt/SYNC.md +5 -0
  105. package/skills/breakdown-epic-arch/LICENSE.md +21 -0
  106. package/skills/breakdown-epic-arch/SKILL.md +66 -0
  107. package/skills/breakdown-epic-arch/SYNC.md +5 -0
  108. package/skills/breakdown-epic-pm/LICENSE.md +21 -0
  109. package/skills/breakdown-epic-pm/SKILL.md +58 -0
  110. package/skills/breakdown-epic-pm/SYNC.md +5 -0
  111. package/skills/breakdown-feature-implementation/LICENSE.md +21 -0
  112. package/skills/breakdown-feature-implementation/SKILL.md +128 -0
  113. package/skills/breakdown-feature-implementation/SYNC.md +5 -0
  114. package/skills/breakdown-feature-prd/LICENSE.md +21 -0
  115. package/skills/breakdown-feature-prd/SKILL.md +61 -0
  116. package/skills/breakdown-feature-prd/SYNC.md +5 -0
  117. package/skills/breakdown-plan/LICENSE.md +21 -0
  118. package/skills/breakdown-plan/SKILL.md +509 -0
  119. package/skills/breakdown-plan/SYNC.md +5 -0
  120. package/skills/breakdown-test/LICENSE.md +21 -0
  121. package/skills/breakdown-test/SKILL.md +365 -0
  122. package/skills/breakdown-test/SYNC.md +5 -0
  123. package/skills/centos-linux-triage/LICENSE.md +21 -0
  124. package/skills/centos-linux-triage/SKILL.md +31 -0
  125. package/skills/centos-linux-triage/SYNC.md +5 -0
  126. package/skills/chrome-devtools/LICENSE.md +21 -0
  127. package/skills/chrome-devtools/SKILL.md +97 -0
  128. package/skills/chrome-devtools/SYNC.md +5 -0
  129. package/skills/cli-mastery/LICENSE.md +21 -0
  130. package/skills/cli-mastery/SKILL.md +43 -0
  131. package/skills/cli-mastery/SYNC.md +5 -0
  132. package/skills/cli-mastery/references/final-exam.md +24 -0
  133. package/skills/cli-mastery/references/module-1-slash-commands.md +88 -0
  134. package/skills/cli-mastery/references/module-2-keyboard-shortcuts.md +38 -0
  135. package/skills/cli-mastery/references/module-3-modes.md +33 -0
  136. package/skills/cli-mastery/references/module-4-agents.md +42 -0
  137. package/skills/cli-mastery/references/module-5-skills.md +33 -0
  138. package/skills/cli-mastery/references/module-6-mcp.md +50 -0
  139. package/skills/cli-mastery/references/module-7-advanced.md +38 -0
  140. package/skills/cli-mastery/references/module-8-configuration.md +34 -0
  141. package/skills/cli-mastery/references/scenarios.md +44 -0
  142. package/skills/cloud-design-patterns/LICENSE.md +21 -0
  143. package/skills/cloud-design-patterns/SKILL.md +62 -0
  144. package/skills/cloud-design-patterns/SYNC.md +5 -0
  145. package/skills/cloud-design-patterns/references/architecture-design.md +127 -0
  146. package/skills/cloud-design-patterns/references/azure-service-mappings.md +13 -0
  147. package/skills/cloud-design-patterns/references/best-practices.md +34 -0
  148. package/skills/cloud-design-patterns/references/deployment-operational.md +91 -0
  149. package/skills/cloud-design-patterns/references/event-driven.md +21 -0
  150. package/skills/cloud-design-patterns/references/messaging-integration.md +127 -0
  151. package/skills/cloud-design-patterns/references/performance.md +180 -0
  152. package/skills/cloud-design-patterns/references/reliability-resilience.md +156 -0
  153. package/skills/cloud-design-patterns/references/security.md +55 -0
  154. package/skills/code-exemplars-blueprint-generator/LICENSE.md +21 -0
  155. package/skills/code-exemplars-blueprint-generator/SKILL.md +126 -0
  156. package/skills/code-exemplars-blueprint-generator/SYNC.md +5 -0
  157. package/skills/codeql/LICENSE.md +21 -0
  158. package/skills/codeql/SKILL.md +405 -0
  159. package/skills/codeql/SYNC.md +5 -0
  160. package/skills/codeql/references/alert-management.md +170 -0
  161. package/skills/codeql/references/cli-commands.md +283 -0
  162. package/skills/codeql/references/compiled-languages.md +284 -0
  163. package/skills/codeql/references/sarif-output.md +265 -0
  164. package/skills/codeql/references/troubleshooting.md +259 -0
  165. package/skills/codeql/references/workflow-configuration.md +398 -0
  166. package/skills/comment-code-generate-a-tutorial/LICENSE.md +21 -0
  167. package/skills/comment-code-generate-a-tutorial/SKILL.md +26 -0
  168. package/skills/comment-code-generate-a-tutorial/SYNC.md +5 -0
  169. package/skills/containerize-aspnet-framework/LICENSE.md +21 -0
  170. package/skills/containerize-aspnet-framework/SKILL.md +454 -0
  171. package/skills/containerize-aspnet-framework/SYNC.md +5 -0
  172. package/skills/containerize-aspnetcore/LICENSE.md +21 -0
  173. package/skills/containerize-aspnetcore/SKILL.md +392 -0
  174. package/skills/containerize-aspnetcore/SYNC.md +5 -0
  175. package/skills/context-map/LICENSE.md +21 -0
  176. package/skills/context-map/SKILL.md +52 -0
  177. package/skills/context-map/SYNC.md +5 -0
  178. package/skills/conventional-commit/LICENSE.md +21 -0
  179. package/skills/conventional-commit/SKILL.md +72 -0
  180. package/skills/conventional-commit/SYNC.md +5 -0
  181. package/skills/convert-plaintext-to-md/LICENSE.md +21 -0
  182. package/skills/convert-plaintext-to-md/SKILL.md +362 -0
  183. package/skills/convert-plaintext-to-md/SYNC.md +5 -0
  184. package/skills/copilot-cli-quickstart/LICENSE.md +21 -0
  185. package/skills/copilot-cli-quickstart/SKILL.md +774 -0
  186. package/skills/copilot-cli-quickstart/SYNC.md +5 -0
  187. package/skills/copilot-instructions-blueprint-generator/LICENSE.md +21 -0
  188. package/skills/copilot-instructions-blueprint-generator/SKILL.md +294 -0
  189. package/skills/copilot-instructions-blueprint-generator/SYNC.md +5 -0
  190. package/skills/copilot-sdk/LICENSE.md +21 -0
  191. package/skills/copilot-sdk/SKILL.md +914 -0
  192. package/skills/copilot-sdk/SYNC.md +5 -0
  193. package/skills/copilot-spaces/LICENSE.md +21 -0
  194. package/skills/copilot-spaces/SKILL.md +205 -0
  195. package/skills/copilot-spaces/SYNC.md +5 -0
  196. package/skills/copilot-usage-metrics/LICENSE.md +21 -0
  197. package/skills/copilot-usage-metrics/SKILL.md +52 -0
  198. package/skills/copilot-usage-metrics/SYNC.md +5 -0
  199. package/skills/copilot-usage-metrics/get-enterprise-metrics.sh +22 -0
  200. package/skills/copilot-usage-metrics/get-enterprise-user-metrics.sh +22 -0
  201. package/skills/copilot-usage-metrics/get-org-metrics.sh +22 -0
  202. package/skills/copilot-usage-metrics/get-org-user-metrics.sh +22 -0
  203. package/skills/cosmosdb-datamodeling/LICENSE.md +21 -0
  204. package/skills/cosmosdb-datamodeling/SKILL.md +1045 -0
  205. package/skills/cosmosdb-datamodeling/SYNC.md +5 -0
  206. package/skills/create-agentsmd/LICENSE.md +21 -0
  207. package/skills/create-agentsmd/SKILL.md +249 -0
  208. package/skills/create-agentsmd/SYNC.md +5 -0
  209. package/skills/create-architectural-decision-record/LICENSE.md +21 -0
  210. package/skills/create-architectural-decision-record/SKILL.md +97 -0
  211. package/skills/create-architectural-decision-record/SYNC.md +5 -0
  212. package/skills/create-github-action-workflow-specification/LICENSE.md +21 -0
  213. package/skills/create-github-action-workflow-specification/SKILL.md +276 -0
  214. package/skills/create-github-action-workflow-specification/SYNC.md +5 -0
  215. package/skills/create-github-issue-feature-from-specification/LICENSE.md +21 -0
  216. package/skills/create-github-issue-feature-from-specification/SKILL.md +28 -0
  217. package/skills/create-github-issue-feature-from-specification/SYNC.md +5 -0
  218. package/skills/create-github-issues-feature-from-implementation-plan/LICENSE.md +21 -0
  219. package/skills/create-github-issues-feature-from-implementation-plan/SKILL.md +28 -0
  220. package/skills/create-github-issues-feature-from-implementation-plan/SYNC.md +5 -0
  221. package/skills/create-github-issues-for-unmet-specification-requirements/LICENSE.md +21 -0
  222. package/skills/create-github-issues-for-unmet-specification-requirements/SKILL.md +35 -0
  223. package/skills/create-github-issues-for-unmet-specification-requirements/SYNC.md +5 -0
  224. package/skills/create-github-pull-request-from-specification/LICENSE.md +21 -0
  225. package/skills/create-github-pull-request-from-specification/SKILL.md +24 -0
  226. package/skills/create-github-pull-request-from-specification/SYNC.md +5 -0
  227. package/skills/create-implementation-plan/LICENSE.md +21 -0
  228. package/skills/create-implementation-plan/SKILL.md +157 -0
  229. package/skills/create-implementation-plan/SYNC.md +5 -0
  230. package/skills/create-llms/LICENSE.md +21 -0
  231. package/skills/create-llms/SKILL.md +210 -0
  232. package/skills/create-llms/SYNC.md +5 -0
  233. package/skills/create-readme/LICENSE.md +21 -0
  234. package/skills/create-readme/SKILL.md +21 -0
  235. package/skills/create-readme/SYNC.md +5 -0
  236. package/skills/create-specification/LICENSE.md +21 -0
  237. package/skills/create-specification/SKILL.md +127 -0
  238. package/skills/create-specification/SYNC.md +5 -0
  239. package/skills/create-spring-boot-java-project/LICENSE.md +21 -0
  240. package/skills/create-spring-boot-java-project/SKILL.md +163 -0
  241. package/skills/create-spring-boot-java-project/SYNC.md +5 -0
  242. package/skills/create-spring-boot-kotlin-project/LICENSE.md +21 -0
  243. package/skills/create-spring-boot-kotlin-project/SKILL.md +147 -0
  244. package/skills/create-spring-boot-kotlin-project/SYNC.md +5 -0
  245. package/skills/create-technical-spike/LICENSE.md +21 -0
  246. package/skills/create-technical-spike/SKILL.md +230 -0
  247. package/skills/create-technical-spike/SYNC.md +5 -0
  248. package/skills/create-tldr-page/LICENSE.md +21 -0
  249. package/skills/create-tldr-page/SKILL.md +210 -0
  250. package/skills/create-tldr-page/SYNC.md +5 -0
  251. package/skills/creating-oracle-to-postgres-master-migration-plan/LICENSE.md +21 -0
  252. package/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md +83 -0
  253. package/skills/creating-oracle-to-postgres-master-migration-plan/SYNC.md +5 -0
  254. package/skills/creating-oracle-to-postgres-migration-bug-report/LICENSE.md +21 -0
  255. package/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md +43 -0
  256. package/skills/creating-oracle-to-postgres-migration-bug-report/SYNC.md +5 -0
  257. package/skills/creating-oracle-to-postgres-migration-bug-report/references/BUG-REPORT-TEMPLATE.md +79 -0
  258. package/skills/creating-oracle-to-postgres-migration-integration-tests/LICENSE.md +21 -0
  259. package/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md +60 -0
  260. package/skills/creating-oracle-to-postgres-migration-integration-tests/SYNC.md +5 -0
  261. package/skills/csharp-async/LICENSE.md +21 -0
  262. package/skills/csharp-async/SKILL.md +49 -0
  263. package/skills/csharp-async/SYNC.md +5 -0
  264. package/skills/csharp-docs/LICENSE.md +21 -0
  265. package/skills/csharp-docs/SKILL.md +62 -0
  266. package/skills/csharp-docs/SYNC.md +5 -0
  267. package/skills/csharp-mcp-server-generator/LICENSE.md +21 -0
  268. package/skills/csharp-mcp-server-generator/SKILL.md +59 -0
  269. package/skills/csharp-mcp-server-generator/SYNC.md +5 -0
  270. package/skills/csharp-mstest/LICENSE.md +21 -0
  271. package/skills/csharp-mstest/SKILL.md +478 -0
  272. package/skills/csharp-mstest/SYNC.md +5 -0
  273. package/skills/csharp-nunit/LICENSE.md +21 -0
  274. package/skills/csharp-nunit/SKILL.md +71 -0
  275. package/skills/csharp-nunit/SYNC.md +5 -0
  276. package/skills/csharp-tunit/LICENSE.md +21 -0
  277. package/skills/csharp-tunit/SKILL.md +100 -0
  278. package/skills/csharp-tunit/SYNC.md +5 -0
  279. package/skills/csharp-xunit/LICENSE.md +21 -0
  280. package/skills/csharp-xunit/SKILL.md +68 -0
  281. package/skills/csharp-xunit/SYNC.md +5 -0
  282. package/skills/datanalysis-credit-risk/LICENSE.md +21 -0
  283. package/skills/datanalysis-credit-risk/SKILL.md +113 -0
  284. package/skills/datanalysis-credit-risk/SYNC.md +5 -0
  285. package/skills/datanalysis-credit-risk/references/analysis.py +1223 -0
  286. package/skills/datanalysis-credit-risk/references/func.py +228 -0
  287. package/skills/datanalysis-credit-risk/scripts/example.py +391 -0
  288. package/skills/dataverse-python-advanced-patterns/LICENSE.md +21 -0
  289. package/skills/dataverse-python-advanced-patterns/SKILL.md +17 -0
  290. package/skills/dataverse-python-advanced-patterns/SYNC.md +5 -0
  291. package/skills/dataverse-python-production-code/LICENSE.md +21 -0
  292. package/skills/dataverse-python-production-code/SKILL.md +116 -0
  293. package/skills/dataverse-python-production-code/SYNC.md +5 -0
  294. package/skills/dataverse-python-quickstart/LICENSE.md +21 -0
  295. package/skills/dataverse-python-quickstart/SKILL.md +14 -0
  296. package/skills/dataverse-python-quickstart/SYNC.md +5 -0
  297. package/skills/dataverse-python-usecase-builder/LICENSE.md +21 -0
  298. package/skills/dataverse-python-usecase-builder/SKILL.md +246 -0
  299. package/skills/dataverse-python-usecase-builder/SYNC.md +5 -0
  300. package/skills/debian-linux-triage/LICENSE.md +21 -0
  301. package/skills/debian-linux-triage/SKILL.md +31 -0
  302. package/skills/debian-linux-triage/SYNC.md +5 -0
  303. package/skills/declarative-agents/LICENSE.md +21 -0
  304. package/skills/declarative-agents/SKILL.md +94 -0
  305. package/skills/declarative-agents/SYNC.md +5 -0
  306. package/skills/dependabot/LICENSE.md +21 -0
  307. package/skills/dependabot/SKILL.md +422 -0
  308. package/skills/dependabot/SYNC.md +5 -0
  309. package/skills/dependabot/references/dependabot-yml-reference.md +374 -0
  310. package/skills/dependabot/references/example-configs.md +409 -0
  311. package/skills/dependabot/references/pr-commands.md +91 -0
  312. package/skills/devops-rollout-plan/LICENSE.md +21 -0
  313. package/skills/devops-rollout-plan/SKILL.md +117 -0
  314. package/skills/devops-rollout-plan/SYNC.md +5 -0
  315. package/skills/documentation-writer/LICENSE.md +21 -0
  316. package/skills/documentation-writer/SKILL.md +45 -0
  317. package/skills/documentation-writer/SYNC.md +5 -0
  318. package/skills/dotnet-best-practices/LICENSE.md +21 -0
  319. package/skills/dotnet-best-practices/SKILL.md +85 -0
  320. package/skills/dotnet-best-practices/SYNC.md +5 -0
  321. package/skills/dotnet-design-pattern-review/LICENSE.md +21 -0
  322. package/skills/dotnet-design-pattern-review/SKILL.md +42 -0
  323. package/skills/dotnet-design-pattern-review/SYNC.md +5 -0
  324. package/skills/dotnet-timezone/LICENSE.md +21 -0
  325. package/skills/dotnet-timezone/SKILL.md +109 -0
  326. package/skills/dotnet-timezone/SYNC.md +5 -0
  327. package/skills/dotnet-timezone/references/code-patterns.md +153 -0
  328. package/skills/dotnet-timezone/references/timezone-index.md +87 -0
  329. package/skills/dotnet-upgrade/LICENSE.md +21 -0
  330. package/skills/dotnet-upgrade/SKILL.md +116 -0
  331. package/skills/dotnet-upgrade/SYNC.md +5 -0
  332. package/skills/doublecheck/LICENSE.md +21 -0
  333. package/skills/doublecheck/SKILL.md +277 -0
  334. package/skills/doublecheck/SYNC.md +5 -0
  335. package/skills/doublecheck/assets/verification-report-template.md +92 -0
  336. package/skills/editorconfig/LICENSE.md +21 -0
  337. package/skills/editorconfig/SKILL.md +63 -0
  338. package/skills/editorconfig/SYNC.md +5 -0
  339. package/skills/ef-core/LICENSE.md +21 -0
  340. package/skills/ef-core/SKILL.md +75 -0
  341. package/skills/ef-core/SYNC.md +5 -0
  342. package/skills/entra-agent-user/LICENSE.md +21 -0
  343. package/skills/entra-agent-user/SKILL.md +270 -0
  344. package/skills/entra-agent-user/SYNC.md +5 -0
  345. package/skills/eval-driven-dev/LICENSE.md +21 -0
  346. package/skills/eval-driven-dev/SKILL.md +862 -0
  347. package/skills/eval-driven-dev/SYNC.md +5 -0
  348. package/skills/eval-driven-dev/references/pixie-api.md +195 -0
  349. package/skills/excalidraw-diagram-generator/LICENSE.md +21 -0
  350. package/skills/excalidraw-diagram-generator/SKILL.md +613 -0
  351. package/skills/excalidraw-diagram-generator/SYNC.md +5 -0
  352. package/skills/excalidraw-diagram-generator/references/element-types.md +497 -0
  353. package/skills/excalidraw-diagram-generator/references/excalidraw-schema.md +350 -0
  354. package/skills/excalidraw-diagram-generator/scripts/README.md +193 -0
  355. package/skills/excalidraw-diagram-generator/scripts/add-arrow.py +312 -0
  356. package/skills/excalidraw-diagram-generator/scripts/add-icon-to-diagram.py +404 -0
  357. package/skills/excalidraw-diagram-generator/scripts/split-excalidraw-library.py +183 -0
  358. package/skills/excalidraw-diagram-generator/templates/business-flow-swimlane-template.excalidraw +334 -0
  359. package/skills/excalidraw-diagram-generator/templates/class-diagram-template.excalidraw +558 -0
  360. package/skills/excalidraw-diagram-generator/templates/data-flow-diagram-template.excalidraw +279 -0
  361. package/skills/excalidraw-diagram-generator/templates/er-diagram-template.excalidraw +662 -0
  362. package/skills/excalidraw-diagram-generator/templates/flowchart-template.excalidraw +179 -0
  363. package/skills/excalidraw-diagram-generator/templates/mindmap-template.excalidraw +244 -0
  364. package/skills/excalidraw-diagram-generator/templates/relationship-template.excalidraw +145 -0
  365. package/skills/excalidraw-diagram-generator/templates/sequence-diagram-template.excalidraw +509 -0
  366. package/skills/fabric-lakehouse/LICENSE.md +21 -0
  367. package/skills/fabric-lakehouse/SKILL.md +106 -0
  368. package/skills/fabric-lakehouse/SYNC.md +5 -0
  369. package/skills/fabric-lakehouse/references/getdata.md +36 -0
  370. package/skills/fabric-lakehouse/references/pyspark.md +189 -0
  371. package/skills/fedora-linux-triage/LICENSE.md +21 -0
  372. package/skills/fedora-linux-triage/SKILL.md +31 -0
  373. package/skills/fedora-linux-triage/SYNC.md +5 -0
  374. package/skills/finalize-agent-prompt/LICENSE.md +21 -0
  375. package/skills/finalize-agent-prompt/SKILL.md +26 -0
  376. package/skills/finalize-agent-prompt/SYNC.md +5 -0
  377. package/skills/finnish-humanizer/LICENSE.md +21 -0
  378. package/skills/finnish-humanizer/SKILL.md +145 -0
  379. package/skills/finnish-humanizer/SYNC.md +5 -0
  380. package/skills/finnish-humanizer/references/patterns.md +338 -0
  381. package/skills/first-ask/LICENSE.md +21 -0
  382. package/skills/first-ask/SKILL.md +30 -0
  383. package/skills/first-ask/SYNC.md +5 -0
  384. package/skills/flowstudio-power-automate-build/LICENSE.md +21 -0
  385. package/skills/flowstudio-power-automate-build/SKILL.md +460 -0
  386. package/skills/flowstudio-power-automate-build/SYNC.md +5 -0
  387. package/skills/flowstudio-power-automate-build/references/action-patterns-connectors.md +542 -0
  388. package/skills/flowstudio-power-automate-build/references/action-patterns-core.md +542 -0
  389. package/skills/flowstudio-power-automate-build/references/action-patterns-data.md +735 -0
  390. package/skills/flowstudio-power-automate-build/references/build-patterns.md +108 -0
  391. package/skills/flowstudio-power-automate-build/references/flow-schema.md +225 -0
  392. package/skills/flowstudio-power-automate-build/references/trigger-types.md +211 -0
  393. package/skills/flowstudio-power-automate-debug/LICENSE.md +21 -0
  394. package/skills/flowstudio-power-automate-debug/SKILL.md +322 -0
  395. package/skills/flowstudio-power-automate-debug/SYNC.md +5 -0
  396. package/skills/flowstudio-power-automate-debug/references/common-errors.md +188 -0
  397. package/skills/flowstudio-power-automate-debug/references/debug-workflow.md +157 -0
  398. package/skills/flowstudio-power-automate-mcp/LICENSE.md +21 -0
  399. package/skills/flowstudio-power-automate-mcp/SKILL.md +450 -0
  400. package/skills/flowstudio-power-automate-mcp/SYNC.md +5 -0
  401. package/skills/flowstudio-power-automate-mcp/references/MCP-BOOTSTRAP.md +53 -0
  402. package/skills/flowstudio-power-automate-mcp/references/action-types.md +79 -0
  403. package/skills/flowstudio-power-automate-mcp/references/connection-references.md +115 -0
  404. package/skills/flowstudio-power-automate-mcp/references/tool-reference.md +445 -0
  405. package/skills/fluentui-blazor/LICENSE.md +21 -0
  406. package/skills/fluentui-blazor/SKILL.md +231 -0
  407. package/skills/fluentui-blazor/SYNC.md +5 -0
  408. package/skills/fluentui-blazor/references/DATAGRID.md +162 -0
  409. package/skills/fluentui-blazor/references/LAYOUT-AND-NAVIGATION.md +173 -0
  410. package/skills/fluentui-blazor/references/SETUP.md +129 -0
  411. package/skills/fluentui-blazor/references/THEMING.md +103 -0
  412. package/skills/folder-structure-blueprint-generator/LICENSE.md +21 -0
  413. package/skills/folder-structure-blueprint-generator/SKILL.md +405 -0
  414. package/skills/folder-structure-blueprint-generator/SYNC.md +5 -0
  415. package/skills/game-engine/LICENSE.md +21 -0
  416. package/skills/game-engine/SKILL.md +139 -0
  417. package/skills/game-engine/SYNC.md +5 -0
  418. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  419. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  420. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  421. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  422. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  423. package/skills/game-engine/references/3d-web-games.md +754 -0
  424. package/skills/game-engine/references/algorithms.md +843 -0
  425. package/skills/game-engine/references/basics.md +343 -0
  426. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  427. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  428. package/skills/game-engine/references/game-publishing.md +352 -0
  429. package/skills/game-engine/references/techniques.md +894 -0
  430. package/skills/game-engine/references/terminology.md +354 -0
  431. package/skills/game-engine/references/web-apis.md +1394 -0
  432. package/skills/gen-specs-as-issues/LICENSE.md +21 -0
  433. package/skills/gen-specs-as-issues/SKILL.md +165 -0
  434. package/skills/gen-specs-as-issues/SYNC.md +5 -0
  435. package/skills/generate-custom-instructions-from-codebase/LICENSE.md +21 -0
  436. package/skills/generate-custom-instructions-from-codebase/SKILL.md +240 -0
  437. package/skills/generate-custom-instructions-from-codebase/SYNC.md +5 -0
  438. package/skills/geofeed-tuner/LICENSE.md +21 -0
  439. package/skills/geofeed-tuner/SKILL.md +864 -0
  440. package/skills/geofeed-tuner/SYNC.md +5 -0
  441. package/skills/geofeed-tuner/assets/example/01-user-input-rfc8805-feed.csv +5 -0
  442. package/skills/geofeed-tuner/assets/iso3166-1.json +1249 -0
  443. package/skills/geofeed-tuner/assets/iso3166-2.json +20188 -0
  444. package/skills/geofeed-tuner/assets/small-territories.json +106 -0
  445. package/skills/geofeed-tuner/references/rfc8805.txt +735 -0
  446. package/skills/geofeed-tuner/references/snippets-python3.md +85 -0
  447. package/skills/geofeed-tuner/scripts/templates/index.html +2305 -0
  448. package/skills/gh-cli/LICENSE.md +21 -0
  449. package/skills/gh-cli/SKILL.md +2187 -0
  450. package/skills/gh-cli/SYNC.md +5 -0
  451. package/skills/git-commit/LICENSE.md +21 -0
  452. package/skills/git-commit/SKILL.md +124 -0
  453. package/skills/git-commit/SYNC.md +5 -0
  454. package/skills/git-flow-branch-creator/LICENSE.md +21 -0
  455. package/skills/git-flow-branch-creator/SKILL.md +292 -0
  456. package/skills/git-flow-branch-creator/SYNC.md +5 -0
  457. package/skills/github-copilot-starter/LICENSE.md +21 -0
  458. package/skills/github-copilot-starter/SKILL.md +402 -0
  459. package/skills/github-copilot-starter/SYNC.md +5 -0
  460. package/skills/github-issues/LICENSE.md +21 -0
  461. package/skills/github-issues/SKILL.md +201 -0
  462. package/skills/github-issues/SYNC.md +5 -0
  463. package/skills/github-issues/references/dependencies.md +71 -0
  464. package/skills/github-issues/references/images.md +116 -0
  465. package/skills/github-issues/references/issue-fields.md +191 -0
  466. package/skills/github-issues/references/issue-types.md +72 -0
  467. package/skills/github-issues/references/projects.md +273 -0
  468. package/skills/github-issues/references/search.md +231 -0
  469. package/skills/github-issues/references/sub-issues.md +137 -0
  470. package/skills/github-issues/references/templates.md +90 -0
  471. package/skills/go-mcp-server-generator/LICENSE.md +21 -0
  472. package/skills/go-mcp-server-generator/SKILL.md +334 -0
  473. package/skills/go-mcp-server-generator/SYNC.md +5 -0
  474. package/skills/gtm-0-to-1-launch/LICENSE.md +21 -0
  475. package/skills/gtm-0-to-1-launch/SKILL.md +321 -0
  476. package/skills/gtm-0-to-1-launch/SYNC.md +5 -0
  477. package/skills/gtm-ai-gtm/LICENSE.md +21 -0
  478. package/skills/gtm-ai-gtm/SKILL.md +569 -0
  479. package/skills/gtm-ai-gtm/SYNC.md +5 -0
  480. package/skills/gtm-board-and-investor-communication/LICENSE.md +21 -0
  481. package/skills/gtm-board-and-investor-communication/SKILL.md +456 -0
  482. package/skills/gtm-board-and-investor-communication/SYNC.md +5 -0
  483. package/skills/gtm-developer-ecosystem/LICENSE.md +21 -0
  484. package/skills/gtm-developer-ecosystem/SKILL.md +310 -0
  485. package/skills/gtm-developer-ecosystem/SYNC.md +5 -0
  486. package/skills/gtm-enterprise-account-planning/LICENSE.md +21 -0
  487. package/skills/gtm-enterprise-account-planning/SKILL.md +429 -0
  488. package/skills/gtm-enterprise-account-planning/SYNC.md +5 -0
  489. package/skills/gtm-enterprise-onboarding/LICENSE.md +21 -0
  490. package/skills/gtm-enterprise-onboarding/SKILL.md +457 -0
  491. package/skills/gtm-enterprise-onboarding/SYNC.md +5 -0
  492. package/skills/gtm-operating-cadence/LICENSE.md +21 -0
  493. package/skills/gtm-operating-cadence/SKILL.md +420 -0
  494. package/skills/gtm-operating-cadence/SYNC.md +5 -0
  495. package/skills/gtm-partnership-architecture/LICENSE.md +21 -0
  496. package/skills/gtm-partnership-architecture/SKILL.md +470 -0
  497. package/skills/gtm-partnership-architecture/SYNC.md +5 -0
  498. package/skills/gtm-positioning-strategy/LICENSE.md +21 -0
  499. package/skills/gtm-positioning-strategy/SKILL.md +438 -0
  500. package/skills/gtm-positioning-strategy/SYNC.md +5 -0
  501. package/skills/gtm-product-led-growth/LICENSE.md +21 -0
  502. package/skills/gtm-product-led-growth/SKILL.md +339 -0
  503. package/skills/gtm-product-led-growth/SYNC.md +5 -0
  504. package/skills/gtm-technical-product-pricing/LICENSE.md +21 -0
  505. package/skills/gtm-technical-product-pricing/SKILL.md +353 -0
  506. package/skills/gtm-technical-product-pricing/SYNC.md +5 -0
  507. package/skills/image-manipulation-image-magick/LICENSE.md +21 -0
  508. package/skills/image-manipulation-image-magick/SKILL.md +252 -0
  509. package/skills/image-manipulation-image-magick/SYNC.md +5 -0
  510. package/skills/import-infrastructure-as-code/LICENSE.md +21 -0
  511. package/skills/import-infrastructure-as-code/SKILL.md +367 -0
  512. package/skills/import-infrastructure-as-code/SYNC.md +5 -0
  513. package/skills/issue-fields-migration/LICENSE.md +21 -0
  514. package/skills/issue-fields-migration/SKILL.md +533 -0
  515. package/skills/issue-fields-migration/SYNC.md +5 -0
  516. package/skills/issue-fields-migration/references/issue-fields-api.md +129 -0
  517. package/skills/issue-fields-migration/references/labels-api.md +74 -0
  518. package/skills/issue-fields-migration/references/projects-api.md +116 -0
  519. package/skills/java-add-graalvm-native-image-support/LICENSE.md +21 -0
  520. package/skills/java-add-graalvm-native-image-support/SKILL.md +449 -0
  521. package/skills/java-add-graalvm-native-image-support/SYNC.md +5 -0
  522. package/skills/java-docs/LICENSE.md +21 -0
  523. package/skills/java-docs/SKILL.md +23 -0
  524. package/skills/java-docs/SYNC.md +5 -0
  525. package/skills/java-junit/LICENSE.md +21 -0
  526. package/skills/java-junit/SKILL.md +63 -0
  527. package/skills/java-junit/SYNC.md +5 -0
  528. package/skills/java-mcp-server-generator/LICENSE.md +21 -0
  529. package/skills/java-mcp-server-generator/SKILL.md +756 -0
  530. package/skills/java-mcp-server-generator/SYNC.md +5 -0
  531. package/skills/java-refactoring-extract-method/LICENSE.md +21 -0
  532. package/skills/java-refactoring-extract-method/SKILL.md +104 -0
  533. package/skills/java-refactoring-extract-method/SYNC.md +5 -0
  534. package/skills/java-refactoring-remove-parameter/LICENSE.md +21 -0
  535. package/skills/java-refactoring-remove-parameter/SKILL.md +84 -0
  536. package/skills/java-refactoring-remove-parameter/SYNC.md +5 -0
  537. package/skills/java-springboot/LICENSE.md +21 -0
  538. package/skills/java-springboot/SKILL.md +65 -0
  539. package/skills/java-springboot/SYNC.md +5 -0
  540. package/skills/javascript-typescript-jest/LICENSE.md +21 -0
  541. package/skills/javascript-typescript-jest/SKILL.md +44 -0
  542. package/skills/javascript-typescript-jest/SYNC.md +5 -0
  543. package/skills/kotlin-mcp-server-generator/LICENSE.md +21 -0
  544. package/skills/kotlin-mcp-server-generator/SKILL.md +449 -0
  545. package/skills/kotlin-mcp-server-generator/SYNC.md +5 -0
  546. package/skills/kotlin-springboot/LICENSE.md +21 -0
  547. package/skills/kotlin-springboot/SKILL.md +70 -0
  548. package/skills/kotlin-springboot/SYNC.md +5 -0
  549. package/skills/legacy-circuit-mockups/LICENSE.md +21 -0
  550. package/skills/legacy-circuit-mockups/SKILL.md +276 -0
  551. package/skills/legacy-circuit-mockups/SYNC.md +5 -0
  552. package/skills/legacy-circuit-mockups/references/28256-eeprom.md +190 -0
  553. package/skills/legacy-circuit-mockups/references/555.md +861 -0
  554. package/skills/legacy-circuit-mockups/references/6502.md +221 -0
  555. package/skills/legacy-circuit-mockups/references/6522.md +211 -0
  556. package/skills/legacy-circuit-mockups/references/6C62256.md +177 -0
  557. package/skills/legacy-circuit-mockups/references/7400-series.md +177 -0
  558. package/skills/legacy-circuit-mockups/references/assembly-compiler.md +258 -0
  559. package/skills/legacy-circuit-mockups/references/assembly-language.md +226 -0
  560. package/skills/legacy-circuit-mockups/references/basic-electronic-components.md +86 -0
  561. package/skills/legacy-circuit-mockups/references/breadboard.md +214 -0
  562. package/skills/legacy-circuit-mockups/references/common-breadboard-components.md +281 -0
  563. package/skills/legacy-circuit-mockups/references/connecting-electronic-components.md +310 -0
  564. package/skills/legacy-circuit-mockups/references/emulator-28256-eeprom.md +245 -0
  565. package/skills/legacy-circuit-mockups/references/emulator-6502.md +251 -0
  566. package/skills/legacy-circuit-mockups/references/emulator-6522.md +288 -0
  567. package/skills/legacy-circuit-mockups/references/emulator-6C62256.md +233 -0
  568. package/skills/legacy-circuit-mockups/references/emulator-lcd.md +266 -0
  569. package/skills/legacy-circuit-mockups/references/lcd.md +208 -0
  570. package/skills/legacy-circuit-mockups/references/minipro.md +211 -0
  571. package/skills/legacy-circuit-mockups/references/t48eeprom-programmer.md +174 -0
  572. package/skills/make-repo-contribution/LICENSE.md +21 -0
  573. package/skills/make-repo-contribution/SKILL.md +90 -0
  574. package/skills/make-repo-contribution/SYNC.md +5 -0
  575. package/skills/make-repo-contribution/assets/issue-template.md +37 -0
  576. package/skills/make-repo-contribution/assets/pr-template.md +36 -0
  577. package/skills/make-skill-template/LICENSE.md +21 -0
  578. package/skills/make-skill-template/SKILL.md +147 -0
  579. package/skills/make-skill-template/SYNC.md +5 -0
  580. package/skills/markdown-to-html/LICENSE.md +21 -0
  581. package/skills/markdown-to-html/SKILL.md +916 -0
  582. package/skills/markdown-to-html/SYNC.md +5 -0
  583. package/skills/markdown-to-html/references/basic-markdown-to-html.md +420 -0
  584. package/skills/markdown-to-html/references/basic-markdown.md +496 -0
  585. package/skills/markdown-to-html/references/code-blocks-to-html.md +165 -0
  586. package/skills/markdown-to-html/references/code-blocks.md +70 -0
  587. package/skills/markdown-to-html/references/collapsed-sections-to-html.md +136 -0
  588. package/skills/markdown-to-html/references/collapsed-sections.md +48 -0
  589. package/skills/markdown-to-html/references/gomarkdown.md +253 -0
  590. package/skills/markdown-to-html/references/hugo.md +394 -0
  591. package/skills/markdown-to-html/references/jekyll.md +321 -0
  592. package/skills/markdown-to-html/references/marked.md +121 -0
  593. package/skills/markdown-to-html/references/pandoc.md +226 -0
  594. package/skills/markdown-to-html/references/tables-to-html.md +169 -0
  595. package/skills/markdown-to-html/references/tables.md +72 -0
  596. package/skills/markdown-to-html/references/writing-mathematical-expressions-to-html.md +350 -0
  597. package/skills/markdown-to-html/references/writing-mathematical-expressions.md +76 -0
  598. package/skills/mcp-cli/LICENSE.md +21 -0
  599. package/skills/mcp-cli/SKILL.md +78 -0
  600. package/skills/mcp-cli/SYNC.md +5 -0
  601. package/skills/mcp-copilot-studio-server-generator/LICENSE.md +21 -0
  602. package/skills/mcp-copilot-studio-server-generator/SKILL.md +118 -0
  603. package/skills/mcp-copilot-studio-server-generator/SYNC.md +5 -0
  604. package/skills/mcp-create-adaptive-cards/LICENSE.md +21 -0
  605. package/skills/mcp-create-adaptive-cards/SKILL.md +532 -0
  606. package/skills/mcp-create-adaptive-cards/SYNC.md +5 -0
  607. package/skills/mcp-create-declarative-agent/LICENSE.md +21 -0
  608. package/skills/mcp-create-declarative-agent/SKILL.md +315 -0
  609. package/skills/mcp-create-declarative-agent/SYNC.md +5 -0
  610. package/skills/mcp-deploy-manage-agents/LICENSE.md +21 -0
  611. package/skills/mcp-deploy-manage-agents/SKILL.md +341 -0
  612. package/skills/mcp-deploy-manage-agents/SYNC.md +5 -0
  613. package/skills/meeting-minutes/LICENSE.md +21 -0
  614. package/skills/meeting-minutes/SKILL.md +235 -0
  615. package/skills/meeting-minutes/SYNC.md +5 -0
  616. package/skills/memory-merger/LICENSE.md +21 -0
  617. package/skills/memory-merger/SKILL.md +108 -0
  618. package/skills/memory-merger/SYNC.md +5 -0
  619. package/skills/mentoring-juniors/LICENSE.md +21 -0
  620. package/skills/mentoring-juniors/SKILL.md +310 -0
  621. package/skills/mentoring-juniors/SYNC.md +5 -0
  622. package/skills/microsoft-agent-framework/LICENSE.md +21 -0
  623. package/skills/microsoft-agent-framework/SKILL.md +65 -0
  624. package/skills/microsoft-agent-framework/SYNC.md +5 -0
  625. package/skills/microsoft-agent-framework/references/dotnet.md +24 -0
  626. package/skills/microsoft-agent-framework/references/python.md +24 -0
  627. package/skills/microsoft-code-reference/LICENSE.md +21 -0
  628. package/skills/microsoft-code-reference/SKILL.md +99 -0
  629. package/skills/microsoft-code-reference/SYNC.md +5 -0
  630. package/skills/microsoft-docs/LICENSE.md +21 -0
  631. package/skills/microsoft-docs/SKILL.md +134 -0
  632. package/skills/microsoft-docs/SYNC.md +5 -0
  633. package/skills/microsoft-skill-creator/LICENSE.md +21 -0
  634. package/skills/microsoft-skill-creator/SKILL.md +250 -0
  635. package/skills/microsoft-skill-creator/SYNC.md +5 -0
  636. package/skills/microsoft-skill-creator/references/skill-templates.md +345 -0
  637. package/skills/migrating-oracle-to-postgres-stored-procedures/LICENSE.md +21 -0
  638. package/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md +42 -0
  639. package/skills/migrating-oracle-to-postgres-stored-procedures/SYNC.md +5 -0
  640. package/skills/mkdocs-translations/LICENSE.md +21 -0
  641. package/skills/mkdocs-translations/SKILL.md +108 -0
  642. package/skills/mkdocs-translations/SYNC.md +5 -0
  643. package/skills/model-recommendation/LICENSE.md +21 -0
  644. package/skills/model-recommendation/SKILL.md +672 -0
  645. package/skills/model-recommendation/SYNC.md +5 -0
  646. package/skills/msstore-cli/LICENSE.md +21 -0
  647. package/skills/msstore-cli/SKILL.md +600 -0
  648. package/skills/msstore-cli/SYNC.md +5 -0
  649. package/skills/multi-stage-dockerfile/LICENSE.md +21 -0
  650. package/skills/multi-stage-dockerfile/SKILL.md +46 -0
  651. package/skills/multi-stage-dockerfile/SYNC.md +5 -0
  652. package/skills/my-issues/LICENSE.md +21 -0
  653. package/skills/my-issues/SKILL.md +8 -0
  654. package/skills/my-issues/SYNC.md +5 -0
  655. package/skills/my-pull-requests/LICENSE.md +21 -0
  656. package/skills/my-pull-requests/SKILL.md +14 -0
  657. package/skills/my-pull-requests/SYNC.md +5 -0
  658. package/skills/nano-banana-pro-openrouter/LICENSE.md +21 -0
  659. package/skills/nano-banana-pro-openrouter/SKILL.md +74 -0
  660. package/skills/nano-banana-pro-openrouter/SYNC.md +5 -0
  661. package/skills/nano-banana-pro-openrouter/assets/SYSTEM_TEMPLATE +14 -0
  662. package/skills/nano-banana-pro-openrouter/scripts/generate_image.py +191 -0
  663. package/skills/napkin/LICENSE.md +21 -0
  664. package/skills/napkin/SKILL.md +154 -0
  665. package/skills/napkin/SYNC.md +5 -0
  666. package/skills/napkin/assets/napkin.html +2019 -0
  667. package/skills/napkin/assets/step1-activate.svg +107 -0
  668. package/skills/napkin/assets/step2-whiteboard.svg +157 -0
  669. package/skills/napkin/assets/step3-draw.svg +143 -0
  670. package/skills/napkin/assets/step4-share.svg +98 -0
  671. package/skills/napkin/assets/step5-response.svg +112 -0
  672. package/skills/next-intl-add-language/LICENSE.md +21 -0
  673. package/skills/next-intl-add-language/SKILL.md +19 -0
  674. package/skills/next-intl-add-language/SYNC.md +5 -0
  675. package/skills/noob-mode/LICENSE.md +21 -0
  676. package/skills/noob-mode/SKILL.md +263 -0
  677. package/skills/noob-mode/SYNC.md +5 -0
  678. package/skills/noob-mode/references/examples.md +418 -0
  679. package/skills/noob-mode/references/glossary.md +368 -0
  680. package/skills/nuget-manager/LICENSE.md +21 -0
  681. package/skills/nuget-manager/SKILL.md +68 -0
  682. package/skills/nuget-manager/SYNC.md +5 -0
  683. package/skills/oo-component-documentation/LICENSE.md +21 -0
  684. package/skills/oo-component-documentation/SKILL.md +74 -0
  685. package/skills/oo-component-documentation/SYNC.md +5 -0
  686. package/skills/oo-component-documentation/assets/documentation-template.md +97 -0
  687. package/skills/oo-component-documentation/references/create-mode.md +32 -0
  688. package/skills/oo-component-documentation/references/update-mode.md +32 -0
  689. package/skills/openapi-to-application-code/LICENSE.md +21 -0
  690. package/skills/openapi-to-application-code/SKILL.md +112 -0
  691. package/skills/openapi-to-application-code/SYNC.md +5 -0
  692. package/skills/pdftk-server/LICENSE.md +21 -0
  693. package/skills/pdftk-server/SKILL.md +162 -0
  694. package/skills/pdftk-server/SYNC.md +5 -0
  695. package/skills/pdftk-server/references/download.md +75 -0
  696. package/skills/pdftk-server/references/pdftk-cli-examples.md +193 -0
  697. package/skills/pdftk-server/references/pdftk-man-page.md +232 -0
  698. package/skills/pdftk-server/references/pdftk-server-license.md +25 -0
  699. package/skills/pdftk-server/references/third-party-materials.md +103 -0
  700. package/skills/penpot-uiux-design/LICENSE.md +21 -0
  701. package/skills/penpot-uiux-design/SKILL.md +342 -0
  702. package/skills/penpot-uiux-design/SYNC.md +5 -0
  703. package/skills/penpot-uiux-design/references/accessibility.md +329 -0
  704. package/skills/penpot-uiux-design/references/component-patterns.md +339 -0
  705. package/skills/penpot-uiux-design/references/platform-guidelines.md +367 -0
  706. package/skills/penpot-uiux-design/references/setup-troubleshooting.md +328 -0
  707. package/skills/php-mcp-server-generator/LICENSE.md +21 -0
  708. package/skills/php-mcp-server-generator/SKILL.md +522 -0
  709. package/skills/php-mcp-server-generator/SYNC.md +5 -0
  710. package/skills/planning-oracle-to-postgres-migration-integration-testing/LICENSE.md +21 -0
  711. package/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md +44 -0
  712. package/skills/planning-oracle-to-postgres-migration-integration-testing/SYNC.md +5 -0
  713. package/skills/plantuml-ascii/LICENSE.md +21 -0
  714. package/skills/plantuml-ascii/SKILL.md +305 -0
  715. package/skills/plantuml-ascii/SYNC.md +5 -0
  716. package/skills/playwright-automation-fill-in-form/LICENSE.md +21 -0
  717. package/skills/playwright-automation-fill-in-form/SKILL.md +28 -0
  718. package/skills/playwright-automation-fill-in-form/SYNC.md +5 -0
  719. package/skills/playwright-explore-website/LICENSE.md +21 -0
  720. package/skills/playwright-explore-website/SKILL.md +17 -0
  721. package/skills/playwright-explore-website/SYNC.md +5 -0
  722. package/skills/playwright-generate-test/LICENSE.md +21 -0
  723. package/skills/playwright-generate-test/SKILL.md +17 -0
  724. package/skills/playwright-generate-test/SYNC.md +5 -0
  725. package/skills/polyglot-test-agent/LICENSE.md +21 -0
  726. package/skills/polyglot-test-agent/SKILL.md +161 -0
  727. package/skills/polyglot-test-agent/SYNC.md +5 -0
  728. package/skills/polyglot-test-agent/unit-test-generation.prompt.md +155 -0
  729. package/skills/postgresql-code-review/LICENSE.md +21 -0
  730. package/skills/postgresql-code-review/SKILL.md +212 -0
  731. package/skills/postgresql-code-review/SYNC.md +5 -0
  732. package/skills/postgresql-optimization/LICENSE.md +21 -0
  733. package/skills/postgresql-optimization/SKILL.md +404 -0
  734. package/skills/postgresql-optimization/SYNC.md +5 -0
  735. package/skills/power-apps-code-app-scaffold/LICENSE.md +21 -0
  736. package/skills/power-apps-code-app-scaffold/SKILL.md +146 -0
  737. package/skills/power-apps-code-app-scaffold/SYNC.md +5 -0
  738. package/skills/power-bi-dax-optimization/LICENSE.md +21 -0
  739. package/skills/power-bi-dax-optimization/SKILL.md +173 -0
  740. package/skills/power-bi-dax-optimization/SYNC.md +5 -0
  741. package/skills/power-bi-model-design-review/LICENSE.md +21 -0
  742. package/skills/power-bi-model-design-review/SKILL.md +403 -0
  743. package/skills/power-bi-model-design-review/SYNC.md +5 -0
  744. package/skills/power-bi-performance-troubleshooting/LICENSE.md +21 -0
  745. package/skills/power-bi-performance-troubleshooting/SKILL.md +382 -0
  746. package/skills/power-bi-performance-troubleshooting/SYNC.md +5 -0
  747. package/skills/power-bi-report-design-consultation/LICENSE.md +21 -0
  748. package/skills/power-bi-report-design-consultation/SKILL.md +351 -0
  749. package/skills/power-bi-report-design-consultation/SYNC.md +5 -0
  750. package/skills/power-platform-mcp-connector-suite/LICENSE.md +21 -0
  751. package/skills/power-platform-mcp-connector-suite/SKILL.md +156 -0
  752. package/skills/power-platform-mcp-connector-suite/SYNC.md +5 -0
  753. package/skills/powerbi-modeling/LICENSE.md +21 -0
  754. package/skills/powerbi-modeling/SKILL.md +153 -0
  755. package/skills/powerbi-modeling/SYNC.md +5 -0
  756. package/skills/powerbi-modeling/references/MEASURES-DAX.md +195 -0
  757. package/skills/powerbi-modeling/references/PERFORMANCE.md +215 -0
  758. package/skills/powerbi-modeling/references/RELATIONSHIPS.md +147 -0
  759. package/skills/powerbi-modeling/references/RLS.md +226 -0
  760. package/skills/powerbi-modeling/references/STAR-SCHEMA.md +103 -0
  761. package/skills/prd/LICENSE.md +21 -0
  762. package/skills/prd/SKILL.md +143 -0
  763. package/skills/prd/SYNC.md +5 -0
  764. package/skills/premium-frontend-ui/LICENSE.md +21 -0
  765. package/skills/premium-frontend-ui/SKILL.md +110 -0
  766. package/skills/premium-frontend-ui/SYNC.md +5 -0
  767. package/skills/project-workflow-analysis-blueprint-generator/LICENSE.md +21 -0
  768. package/skills/project-workflow-analysis-blueprint-generator/SKILL.md +293 -0
  769. package/skills/project-workflow-analysis-blueprint-generator/SYNC.md +5 -0
  770. package/skills/prompt-builder/LICENSE.md +21 -0
  771. package/skills/prompt-builder/SKILL.md +141 -0
  772. package/skills/prompt-builder/SYNC.md +5 -0
  773. package/skills/publish-to-pages/LICENSE.md +21 -0
  774. package/skills/publish-to-pages/SKILL.md +107 -0
  775. package/skills/publish-to-pages/SYNC.md +5 -0
  776. package/skills/publish-to-pages/scripts/convert-pdf.py +176 -0
  777. package/skills/publish-to-pages/scripts/convert-pptx.py +376 -0
  778. package/skills/publish-to-pages/scripts/publish.sh +51 -0
  779. package/skills/pytest-coverage/LICENSE.md +21 -0
  780. package/skills/pytest-coverage/SKILL.md +28 -0
  781. package/skills/pytest-coverage/SYNC.md +5 -0
  782. package/skills/python-mcp-server-generator/LICENSE.md +21 -0
  783. package/skills/python-mcp-server-generator/SKILL.md +105 -0
  784. package/skills/python-mcp-server-generator/SYNC.md +5 -0
  785. package/skills/quasi-coder/LICENSE.md +21 -0
  786. package/skills/quasi-coder/SKILL.md +369 -0
  787. package/skills/quasi-coder/SYNC.md +5 -0
  788. package/skills/readme-blueprint-generator/LICENSE.md +21 -0
  789. package/skills/readme-blueprint-generator/SKILL.md +78 -0
  790. package/skills/readme-blueprint-generator/SYNC.md +5 -0
  791. package/skills/refactor/LICENSE.md +21 -0
  792. package/skills/refactor/SKILL.md +645 -0
  793. package/skills/refactor/SYNC.md +5 -0
  794. package/skills/refactor-method-complexity-reduce/LICENSE.md +21 -0
  795. package/skills/refactor-method-complexity-reduce/SKILL.md +98 -0
  796. package/skills/refactor-method-complexity-reduce/SYNC.md +5 -0
  797. package/skills/refactor-plan/LICENSE.md +21 -0
  798. package/skills/refactor-plan/SKILL.md +65 -0
  799. package/skills/refactor-plan/SYNC.md +5 -0
  800. package/skills/remember/LICENSE.md +21 -0
  801. package/skills/remember/SKILL.md +126 -0
  802. package/skills/remember/SYNC.md +5 -0
  803. package/skills/remember-interactive-programming/LICENSE.md +21 -0
  804. package/skills/remember-interactive-programming/SKILL.md +13 -0
  805. package/skills/remember-interactive-programming/SYNC.md +5 -0
  806. package/skills/repo-story-time/LICENSE.md +21 -0
  807. package/skills/repo-story-time/SKILL.md +154 -0
  808. package/skills/repo-story-time/SYNC.md +5 -0
  809. package/skills/review-and-refactor/LICENSE.md +21 -0
  810. package/skills/review-and-refactor/SKILL.md +15 -0
  811. package/skills/review-and-refactor/SYNC.md +5 -0
  812. package/skills/reviewing-oracle-to-postgres-migration/LICENSE.md +21 -0
  813. package/skills/reviewing-oracle-to-postgres-migration/SKILL.md +67 -0
  814. package/skills/reviewing-oracle-to-postgres-migration/SYNC.md +5 -0
  815. package/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md +13 -0
  816. package/skills/reviewing-oracle-to-postgres-migration/references/empty-strings-handling.md +69 -0
  817. package/skills/reviewing-oracle-to-postgres-migration/references/no-data-found-exceptions.md +99 -0
  818. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-parentheses-from-clause.md +190 -0
  819. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md +51 -0
  820. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-timestamp-timezone.md +187 -0
  821. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-to-char-numeric.md +145 -0
  822. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-type-coercion.md +182 -0
  823. package/skills/reviewing-oracle-to-postgres-migration/references/postgres-concurrent-transactions.md +259 -0
  824. package/skills/reviewing-oracle-to-postgres-migration/references/postgres-refcursor-handling.md +148 -0
  825. package/skills/ruby-mcp-server-generator/LICENSE.md +21 -0
  826. package/skills/ruby-mcp-server-generator/SKILL.md +660 -0
  827. package/skills/ruby-mcp-server-generator/SYNC.md +5 -0
  828. package/skills/rust-mcp-server-generator/LICENSE.md +21 -0
  829. package/skills/rust-mcp-server-generator/SKILL.md +577 -0
  830. package/skills/rust-mcp-server-generator/SYNC.md +5 -0
  831. package/skills/sandbox-npm-install/LICENSE.md +21 -0
  832. package/skills/sandbox-npm-install/SKILL.md +80 -0
  833. package/skills/sandbox-npm-install/SYNC.md +5 -0
  834. package/skills/sandbox-npm-install/scripts/install.sh +193 -0
  835. package/skills/scaffolding-oracle-to-postgres-migration-test-project/LICENSE.md +21 -0
  836. package/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md +54 -0
  837. package/skills/scaffolding-oracle-to-postgres-migration-test-project/SYNC.md +5 -0
  838. package/skills/scoutqa-test/LICENSE.md +21 -0
  839. package/skills/scoutqa-test/SKILL.md +375 -0
  840. package/skills/scoutqa-test/SYNC.md +5 -0
  841. package/skills/secret-scanning/LICENSE.md +21 -0
  842. package/skills/secret-scanning/SKILL.md +224 -0
  843. package/skills/secret-scanning/SYNC.md +5 -0
  844. package/skills/secret-scanning/references/alerts-and-remediation.md +245 -0
  845. package/skills/secret-scanning/references/custom-patterns.md +158 -0
  846. package/skills/secret-scanning/references/push-protection.md +164 -0
  847. package/skills/semantic-kernel/LICENSE.md +21 -0
  848. package/skills/semantic-kernel/SKILL.md +56 -0
  849. package/skills/semantic-kernel/SYNC.md +5 -0
  850. package/skills/semantic-kernel/references/dotnet.md +15 -0
  851. package/skills/semantic-kernel/references/python.md +15 -0
  852. package/skills/shuffle-json-data/LICENSE.md +21 -0
  853. package/skills/shuffle-json-data/SKILL.md +150 -0
  854. package/skills/shuffle-json-data/SYNC.md +5 -0
  855. package/skills/snowflake-semanticview/LICENSE.md +21 -0
  856. package/skills/snowflake-semanticview/SKILL.md +83 -0
  857. package/skills/snowflake-semanticview/SYNC.md +5 -0
  858. package/skills/sponsor-finder/LICENSE.md +21 -0
  859. package/skills/sponsor-finder/SKILL.md +258 -0
  860. package/skills/sponsor-finder/SYNC.md +5 -0
  861. package/skills/spring-boot-testing/LICENSE.md +21 -0
  862. package/skills/spring-boot-testing/SKILL.md +189 -0
  863. package/skills/spring-boot-testing/SYNC.md +5 -0
  864. package/skills/spring-boot-testing/references/assertj-basics.md +207 -0
  865. package/skills/spring-boot-testing/references/assertj-collections.md +183 -0
  866. package/skills/spring-boot-testing/references/context-caching.md +115 -0
  867. package/skills/spring-boot-testing/references/datajpatest.md +197 -0
  868. package/skills/spring-boot-testing/references/instancio.md +230 -0
  869. package/skills/spring-boot-testing/references/mockitobean.md +232 -0
  870. package/skills/spring-boot-testing/references/mockmvc-classic.md +206 -0
  871. package/skills/spring-boot-testing/references/mockmvc-tester.md +311 -0
  872. package/skills/spring-boot-testing/references/restclienttest.md +227 -0
  873. package/skills/spring-boot-testing/references/resttestclient.md +278 -0
  874. package/skills/spring-boot-testing/references/sb4-migration.md +181 -0
  875. package/skills/spring-boot-testing/references/test-slices-overview.md +203 -0
  876. package/skills/spring-boot-testing/references/testcontainers-jdbc.md +234 -0
  877. package/skills/spring-boot-testing/references/webmvctest.md +177 -0
  878. package/skills/sql-code-review/LICENSE.md +21 -0
  879. package/skills/sql-code-review/SKILL.md +301 -0
  880. package/skills/sql-code-review/SYNC.md +5 -0
  881. package/skills/sql-optimization/LICENSE.md +21 -0
  882. package/skills/sql-optimization/SKILL.md +296 -0
  883. package/skills/sql-optimization/SYNC.md +5 -0
  884. package/skills/structured-autonomy-generate/LICENSE.md +21 -0
  885. package/skills/structured-autonomy-generate/SKILL.md +125 -0
  886. package/skills/structured-autonomy-generate/SYNC.md +5 -0
  887. package/skills/structured-autonomy-implement/LICENSE.md +21 -0
  888. package/skills/structured-autonomy-implement/SKILL.md +19 -0
  889. package/skills/structured-autonomy-implement/SYNC.md +5 -0
  890. package/skills/structured-autonomy-plan/LICENSE.md +21 -0
  891. package/skills/structured-autonomy-plan/SKILL.md +81 -0
  892. package/skills/structured-autonomy-plan/SYNC.md +5 -0
  893. package/skills/suggest-awesome-github-copilot-agents/LICENSE.md +21 -0
  894. package/skills/suggest-awesome-github-copilot-agents/SKILL.md +106 -0
  895. package/skills/suggest-awesome-github-copilot-agents/SYNC.md +5 -0
  896. package/skills/suggest-awesome-github-copilot-instructions/LICENSE.md +21 -0
  897. package/skills/suggest-awesome-github-copilot-instructions/SKILL.md +122 -0
  898. package/skills/suggest-awesome-github-copilot-instructions/SYNC.md +5 -0
  899. package/skills/suggest-awesome-github-copilot-skills/LICENSE.md +21 -0
  900. package/skills/suggest-awesome-github-copilot-skills/SKILL.md +130 -0
  901. package/skills/suggest-awesome-github-copilot-skills/SYNC.md +5 -0
  902. package/skills/swift-mcp-server-generator/LICENSE.md +21 -0
  903. package/skills/swift-mcp-server-generator/SKILL.md +669 -0
  904. package/skills/swift-mcp-server-generator/SYNC.md +5 -0
  905. package/skills/technology-stack-blueprint-generator/LICENSE.md +21 -0
  906. package/skills/technology-stack-blueprint-generator/SKILL.md +242 -0
  907. package/skills/technology-stack-blueprint-generator/SYNC.md +5 -0
  908. package/skills/terraform-azurerm-set-diff-analyzer/LICENSE.md +21 -0
  909. package/skills/terraform-azurerm-set-diff-analyzer/SKILL.md +48 -0
  910. package/skills/terraform-azurerm-set-diff-analyzer/SYNC.md +5 -0
  911. package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.json +154 -0
  912. package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.md +145 -0
  913. package/skills/terraform-azurerm-set-diff-analyzer/scripts/README.md +205 -0
  914. package/skills/terraform-azurerm-set-diff-analyzer/scripts/analyze_plan.py +940 -0
  915. package/skills/tldr-prompt/LICENSE.md +21 -0
  916. package/skills/tldr-prompt/SKILL.md +304 -0
  917. package/skills/tldr-prompt/SYNC.md +5 -0
  918. package/skills/transloadit-media-processing/LICENSE.md +21 -0
  919. package/skills/transloadit-media-processing/SKILL.md +194 -0
  920. package/skills/transloadit-media-processing/SYNC.md +5 -0
  921. package/skills/typescript-mcp-server-generator/LICENSE.md +21 -0
  922. package/skills/typescript-mcp-server-generator/SKILL.md +90 -0
  923. package/skills/typescript-mcp-server-generator/SYNC.md +5 -0
  924. package/skills/typespec-api-operations/LICENSE.md +21 -0
  925. package/skills/typespec-api-operations/SKILL.md +418 -0
  926. package/skills/typespec-api-operations/SYNC.md +5 -0
  927. package/skills/typespec-create-agent/LICENSE.md +21 -0
  928. package/skills/typespec-create-agent/SKILL.md +91 -0
  929. package/skills/typespec-create-agent/SYNC.md +5 -0
  930. package/skills/typespec-create-api-plugin/LICENSE.md +21 -0
  931. package/skills/typespec-create-api-plugin/SKILL.md +164 -0
  932. package/skills/typespec-create-api-plugin/SYNC.md +5 -0
  933. package/skills/unit-test-vue-pinia/LICENSE.md +21 -0
  934. package/skills/unit-test-vue-pinia/SKILL.md +198 -0
  935. package/skills/unit-test-vue-pinia/SYNC.md +5 -0
  936. package/skills/unit-test-vue-pinia/references/pinia-patterns.md +95 -0
  937. package/skills/update-avm-modules-in-bicep/LICENSE.md +21 -0
  938. package/skills/update-avm-modules-in-bicep/SKILL.md +60 -0
  939. package/skills/update-avm-modules-in-bicep/SYNC.md +5 -0
  940. package/skills/update-implementation-plan/LICENSE.md +21 -0
  941. package/skills/update-implementation-plan/SKILL.md +157 -0
  942. package/skills/update-implementation-plan/SYNC.md +5 -0
  943. package/skills/update-llms/LICENSE.md +21 -0
  944. package/skills/update-llms/SKILL.md +216 -0
  945. package/skills/update-llms/SYNC.md +5 -0
  946. package/skills/update-markdown-file-index/LICENSE.md +21 -0
  947. package/skills/update-markdown-file-index/SKILL.md +76 -0
  948. package/skills/update-markdown-file-index/SYNC.md +5 -0
  949. package/skills/update-specification/LICENSE.md +21 -0
  950. package/skills/update-specification/SKILL.md +127 -0
  951. package/skills/update-specification/SYNC.md +5 -0
  952. package/skills/vscode-ext-commands/LICENSE.md +21 -0
  953. package/skills/vscode-ext-commands/SKILL.md +21 -0
  954. package/skills/vscode-ext-commands/SYNC.md +5 -0
  955. package/skills/vscode-ext-localization/LICENSE.md +21 -0
  956. package/skills/vscode-ext-localization/SKILL.md +25 -0
  957. package/skills/vscode-ext-localization/SYNC.md +5 -0
  958. package/skills/web-coder/LICENSE.md +21 -0
  959. package/skills/web-coder/SKILL.md +563 -0
  960. package/skills/web-coder/SYNC.md +5 -0
  961. package/skills/web-coder/references/accessibility.md +346 -0
  962. package/skills/web-coder/references/architecture-patterns.md +625 -0
  963. package/skills/web-coder/references/browsers-engines.md +358 -0
  964. package/skills/web-coder/references/css-styling.md +696 -0
  965. package/skills/web-coder/references/data-formats-encoding.md +411 -0
  966. package/skills/web-coder/references/development-tools.md +502 -0
  967. package/skills/web-coder/references/glossary.md +649 -0
  968. package/skills/web-coder/references/html-markup.md +387 -0
  969. package/skills/web-coder/references/http-networking.md +538 -0
  970. package/skills/web-coder/references/javascript-programming.md +807 -0
  971. package/skills/web-coder/references/media-graphics.md +504 -0
  972. package/skills/web-coder/references/performance-optimization.md +546 -0
  973. package/skills/web-coder/references/security-authentication.md +603 -0
  974. package/skills/web-coder/references/servers-infrastructure.md +615 -0
  975. package/skills/web-coder/references/web-apis-dom.md +654 -0
  976. package/skills/web-coder/references/web-protocols-standards.md +265 -0
  977. package/skills/web-design-reviewer/LICENSE.md +21 -0
  978. package/skills/web-design-reviewer/SKILL.md +368 -0
  979. package/skills/web-design-reviewer/SYNC.md +5 -0
  980. package/skills/web-design-reviewer/references/framework-fixes.md +475 -0
  981. package/skills/web-design-reviewer/references/visual-checklist.md +236 -0
  982. package/skills/webapp-testing/LICENSE.md +21 -0
  983. package/skills/webapp-testing/SKILL.md +104 -67
  984. package/skills/webapp-testing/SYNC.md +2 -2
  985. package/skills/webapp-testing/assets/test-helper.js +56 -0
  986. package/skills/what-context-needed/LICENSE.md +21 -0
  987. package/skills/what-context-needed/SKILL.md +39 -0
  988. package/skills/what-context-needed/SYNC.md +5 -0
  989. package/skills/winapp-cli/LICENSE.md +21 -0
  990. package/skills/winapp-cli/SKILL.md +217 -0
  991. package/skills/winapp-cli/SYNC.md +5 -0
  992. package/skills/winmd-api-search/LICENSE.md +21 -0
  993. package/skills/winmd-api-search/LICENSE.txt +21 -0
  994. package/skills/winmd-api-search/SKILL.md +192 -0
  995. package/skills/winmd-api-search/SYNC.md +5 -0
  996. package/skills/winmd-api-search/scripts/Invoke-WinMdQuery.ps1 +505 -0
  997. package/skills/winmd-api-search/scripts/Update-WinMdCache.ps1 +208 -0
  998. package/skills/winmd-api-search/scripts/cache-generator/CacheGenerator.csproj +29 -0
  999. package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.props +3 -0
  1000. package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.targets +3 -0
  1001. package/skills/winmd-api-search/scripts/cache-generator/Directory.Packages.props +3 -0
  1002. package/skills/winmd-api-search/scripts/cache-generator/Program.cs +1222 -0
  1003. package/skills/winui3-migration-guide/LICENSE.md +21 -0
  1004. package/skills/winui3-migration-guide/SKILL.md +277 -0
  1005. package/skills/winui3-migration-guide/SYNC.md +5 -0
  1006. package/skills/workiq-copilot/LICENSE.md +21 -0
  1007. package/skills/workiq-copilot/SKILL.md +98 -0
  1008. package/skills/workiq-copilot/SYNC.md +5 -0
  1009. package/skills/write-coding-standards-from-file/LICENSE.md +21 -0
  1010. package/skills/write-coding-standards-from-file/SKILL.md +316 -0
  1011. package/skills/write-coding-standards-from-file/SYNC.md +5 -0
  1012. package/skills/webapp-testing/LICENSE.txt +0 -202
  1013. package/skills/webapp-testing/examples/console_logging.py +0 -35
  1014. package/skills/webapp-testing/examples/element_discovery.py +0 -40
  1015. package/skills/webapp-testing/examples/static_html_automation.py +0 -33
  1016. package/skills/webapp-testing/scripts/with_server.py +0 -106
@@ -0,0 +1,1223 @@
1
+ """Variable selection and analysis module - simplified version
2
+ PSI calculation is reused in func.py, analysis.py only handles variable selection
3
+ """
4
+ import pandas as pd
5
+ import numpy as np
6
+ import toad
7
+ from typing import List, Dict, Tuple
8
+ from openpyxl import Workbook
9
+ from openpyxl.styles import Font, PatternFill, Alignment
10
+ from datetime import datetime
11
+ import lightgbm as lgb
12
+ from sklearn.model_selection import train_test_split
13
+ from sklearn.metrics import roc_auc_score
14
+ from joblib import Parallel, delayed
15
+
16
+
17
+ def drop_abnormal_ym(data: pd.DataFrame, min_ym_bad_sample: int = 1,
18
+ min_ym_sample: int = 500) -> tuple:
19
+ """Filter abnormal months - overall statistics, not by organization"""
20
+ stat = data.groupby('new_date_ym').agg(
21
+ bad_cnt=('new_target', 'sum'),
22
+ total=('new_target', 'count')
23
+ ).reset_index()
24
+
25
+ abnormal = stat[(stat['bad_cnt'] < min_ym_bad_sample) | (stat['total'] < min_ym_sample)]
26
+ abnormal = abnormal.rename(columns={'new_date_ym': '年月'})
27
+ abnormal['去除条件'] = abnormal.apply(
28
+ lambda x: f'bad sample count {x["bad_cnt"]} less than {min_ym_bad_sample}' if x['bad_cnt'] < min_ym_bad_sample else f'total sample count {x["total"]} less than {min_ym_sample}', axis=1
29
+ )
30
+
31
+ if len(abnormal) > 0:
32
+ data = data[~data['new_date_ym'].isin(abnormal['年月'])]
33
+
34
+ # Remove empty rows
35
+ abnormal = abnormal.dropna(how='all')
36
+ abnormal = abnormal.reset_index(drop=True)
37
+
38
+ return data, abnormal
39
+
40
+
41
+ def drop_highmiss_features(data: pd.DataFrame, miss_channel: pd.DataFrame,
42
+ threshold: float = 0.6) -> tuple:
43
+ """Drop high missing rate features"""
44
+ high_miss = miss_channel[miss_channel['整体缺失率'] > threshold].copy()
45
+ high_miss['缺失率'] = high_miss['整体缺失率']
46
+
47
+ # Modify removal condition to show specific missing rate value
48
+ high_miss['去除条件'] = high_miss.apply(
49
+ lambda x: f'overall missing rate is {x["缺失率"]:.4f}, exceeds threshold {threshold}', axis=1
50
+ )
51
+
52
+ # Remove empty rows
53
+ high_miss = high_miss.dropna(how='all')
54
+ high_miss = high_miss.reset_index(drop=True)
55
+
56
+ # Drop high missing rate features
57
+ if len(high_miss) > 0 and '变量' in high_miss.columns:
58
+ to_drop = high_miss['变量'].tolist()
59
+ data = data.drop(columns=[c for c in to_drop if c in data.columns])
60
+
61
+ return data, high_miss[['变量', '缺失率', '去除条件']]
62
+
63
+
64
+ def drop_lowiv_features(data: pd.DataFrame, features: List[str],
65
+ overall_iv_threshold: float = 0.05, org_iv_threshold: float = 0.02,
66
+ max_org_threshold: int = 8, n_jobs: int = 4) -> tuple:
67
+ """Drop low IV features - multi-process version, returns IV details and IV processing table
68
+
69
+ Args:
70
+ overall_iv_threshold: Overall IV threshold, values below this are recorded in IV processing table
71
+ org_iv_threshold: Single organization IV threshold, values below this are considered not satisfied
72
+ max_org_threshold: Maximum tolerated organization count, if more than this number of organizations have IV below threshold, record in IV processing table
73
+
74
+ Returns:
75
+ data: Data after dropping
76
+ iv_detail: IV details (IV value of each feature in each organization and overall)
77
+ iv_process: IV processing table (features that do not meet the conditions)
78
+ """
79
+ from references.func import calculate_iv
80
+ from joblib import Parallel, delayed
81
+
82
+ orgs = sorted(data['new_org'].unique())
83
+
84
+ print(f" IV calculation: feature count={len(features)}, organization count={len(orgs)}")
85
+
86
+ # Calculate IV values for all organizations at once
87
+ def _calc_org_iv(org):
88
+ org_data = data[data['new_org'] == org]
89
+ org_iv = calculate_iv(org_data, features, n_jobs=1)
90
+ if len(org_iv) > 0:
91
+ org_iv = org_iv.rename(columns={'IV': 'IV值'})
92
+ org_iv['机构'] = org
93
+ return org_iv
94
+ return None
95
+
96
+ # Calculate overall IV
97
+ print(f" Calculating overall IV...")
98
+ iv_overall = calculate_iv(data, features, n_jobs=n_jobs)
99
+ print(f" Overall IV calculation result: {len(iv_overall)} features")
100
+ if len(iv_overall) == 0:
101
+ print(f" Warning: Overall IV calculation result is empty, returning empty table")
102
+ return data, pd.DataFrame(columns=['变量', 'IV值', '机构', '类型']), pd.DataFrame(columns=['变量', '整体IV', '低IV机构数', '处理原因'])
103
+ iv_overall = iv_overall.rename(columns={'IV': 'IV值'})
104
+
105
+ # Parallel calculation of IV values for all organizations
106
+ print(f" Parallel calculation of IV values for {len(orgs)} organizations...")
107
+ iv_by_org_results = Parallel(n_jobs=n_jobs, verbose=0)(
108
+ delayed(_calc_org_iv)(org) for org in orgs
109
+ )
110
+ iv_by_org = [r for r in iv_by_org_results if r is not None]
111
+ iv_by_org = pd.concat(iv_by_org, ignore_index=True) if iv_by_org else pd.DataFrame(columns=['变量', 'IV值', '机构'])
112
+ print(f" Organization IV summary: {len(iv_by_org)} records")
113
+
114
+ # Convert to wide format: feature, overall, org1, org2, ..., orgn
115
+ iv_detail_dict = {'变量': []}
116
+ iv_detail_dict['整体'] = []
117
+
118
+ for org in orgs:
119
+ iv_detail_dict[org] = []
120
+
121
+ # Get all features
122
+ all_vars = set(iv_overall['变量'].tolist())
123
+ if len(iv_by_org) > 0:
124
+ all_vars.update(iv_by_org['变量'].tolist())
125
+ all_vars = sorted(all_vars)
126
+
127
+ for var in all_vars:
128
+ iv_detail_dict['变量'].append(var)
129
+
130
+ # Overall IV
131
+ var_overall = iv_overall[iv_overall['变量'] == var]
132
+ if len(var_overall) > 0:
133
+ iv_detail_dict['整体'].append(var_overall['IV值'].values[0])
134
+ else:
135
+ iv_detail_dict['整体'].append(None)
136
+
137
+ # IV for each organization
138
+ for org in orgs:
139
+ var_org = iv_by_org[iv_by_org['机构'] == org]
140
+ var_org = var_org[var_org['变量'] == var]
141
+ if len(var_org) > 0:
142
+ iv_detail_dict[org].append(var_org['IV值'].values[0])
143
+ else:
144
+ iv_detail_dict[org].append(None)
145
+
146
+ iv_detail = pd.DataFrame(iv_detail_dict)
147
+ # Sort by overall IV in descending order
148
+ iv_detail = iv_detail.sort_values('整体', ascending=False)
149
+ iv_detail = iv_detail.reset_index(drop=True)
150
+
151
+ # Mark features that do not meet conditions
152
+ # 1. Overall IV below threshold
153
+ iv_overall_low = iv_overall[iv_overall['IV值'] < overall_iv_threshold]['变量'].tolist()
154
+
155
+ # 2. Number of organizations with single organization IV below threshold
156
+ if len(iv_by_org) > 0:
157
+ iv_by_org_low = iv_by_org[iv_by_org['IV值'] < org_iv_threshold].groupby('变量').size().reset_index()
158
+ iv_by_org_low.columns = ['变量', '低IV机构数']
159
+ else:
160
+ iv_by_org_low = pd.DataFrame(columns=['变量', '低IV机构数'])
161
+
162
+ # Get list of low IV organizations for each feature
163
+ low_iv_orgs_dict = {}
164
+ if len(iv_by_org) > 0:
165
+ for var in iv_by_org['变量'].unique():
166
+ var_orgs = iv_by_org[(iv_by_org['变量'] == var) & (iv_by_org['IV值'] < org_iv_threshold)]['机构'].tolist()
167
+ low_iv_orgs_dict[var] = var_orgs
168
+
169
+ # 3. Mark features that need processing
170
+ iv_process = []
171
+
172
+ # Debug info: IV distribution statistics
173
+ if len(iv_overall) > 0:
174
+ print(f" Overall IV statistics: min={iv_overall['IV值'].min():.4f}, max={iv_overall['IV值'].max():.4f}, median={iv_overall['IV值'].median():.4f}")
175
+ print(f" Number of features with overall IV less than {overall_iv_threshold}: {(iv_overall['IV值'] < overall_iv_threshold).sum()}/{len(iv_overall)}")
176
+
177
+ if len(iv_by_org_low) > 0:
178
+ print(f" Statistics of features with organization IV less than {org_iv_threshold}:")
179
+ print(f" Maximum low IV organization count: {iv_by_org_low['低IV机构数'].max()}")
180
+ print(f" Number of features with low IV organization count greater than or equal to {max_org_threshold}: {(iv_by_org_low['低IV机构数'] >= max_org_threshold).sum()}/{len(iv_by_org_low)}")
181
+
182
+ for var in features:
183
+ reasons = []
184
+
185
+ # Check overall IV
186
+ var_overall_iv = iv_overall[iv_overall['变量'] == var]['IV值'].values
187
+ if len(var_overall_iv) > 0 and var_overall_iv[0] < overall_iv_threshold:
188
+ reasons.append(f'overall IV {var_overall_iv[0]:.4f} less than threshold {overall_iv_threshold}')
189
+
190
+ # Check organization IV
191
+ var_org_low = iv_by_org_low[iv_by_org_low['变量'] == var]
192
+ if len(var_org_low) > 0 and var_org_low['低IV机构数'].values[0] >= max_org_threshold:
193
+ reasons.append(f'IV less than threshold {org_iv_threshold} in {var_org_low["低IV机构数"].values[0]} organizations')
194
+
195
+ if reasons:
196
+ iv_process.append({
197
+ '变量': var,
198
+ '处理原因': '; '.join(reasons),
199
+ '低IV机构': ','.join(low_iv_orgs_dict.get(var, []))
200
+ })
201
+
202
+ iv_process = pd.DataFrame(iv_process)
203
+ iv_process = iv_process.reset_index(drop=True)
204
+
205
+ # Drop features that do not meet conditions
206
+ if len(iv_process) > 0 and '变量' in iv_process.columns:
207
+ to_drop = iv_process['变量'].tolist()
208
+ data = data.drop(columns=[c for c in to_drop if c in data.columns])
209
+
210
+ return data, iv_detail, iv_process
211
+
212
+
213
+ def drop_highcorr_features(data: pd.DataFrame, features: List[str],
214
+ threshold: float = 0.8, gain_dict: dict = None, top_n_keep: int = 20) -> tuple:
215
+ """Drop high correlation features - based on original gain, drop one feature at a time
216
+
217
+ Args:
218
+ data: Data
219
+ features: Feature list
220
+ threshold: Correlation threshold
221
+ gain_dict: Mapping dictionary from feature to original gain
222
+ top_n_keep: Keep top N features by original gain ranking
223
+
224
+ Returns:
225
+ data: Data after dropping
226
+ dropped_info: Drop information
227
+ """
228
+ if gain_dict is None:
229
+ gain_dict = {}
230
+
231
+ # Get current feature list (only features that exist in data)
232
+ current_features = [f for f in features if f in data.columns]
233
+
234
+ if len(current_features) == 0:
235
+ return data, pd.DataFrame(columns=['变量', '相关变量', '去除条件'])
236
+
237
+ # Determine features to keep (top N by original gain)
238
+ if gain_dict:
239
+ # Only consider features that exist in current features
240
+ current_gain_dict = {k: v for k, v in gain_dict.items() if k in current_features}
241
+ if current_gain_dict:
242
+ sorted_features = sorted(current_gain_dict.keys(), key=lambda x: current_gain_dict[x], reverse=True)
243
+ top_features = set(sorted_features[:top_n_keep])
244
+ # Create mapping from feature to ranking
245
+ rank_dict = {v: i+1 for i, v in enumerate(sorted_features)}
246
+ else:
247
+ top_features = set()
248
+ rank_dict = {}
249
+ else:
250
+ top_features = set()
251
+ rank_dict = {}
252
+
253
+ dropped_info = []
254
+
255
+ # Loop to drop until no high correlation feature pairs
256
+ while True:
257
+ # Recalculate correlation matrix (only for current remaining features)
258
+ current_features = [f for f in current_features if f in data.columns]
259
+ if len(current_features) < 2:
260
+ break
261
+
262
+ corr = data[current_features].corr().abs()
263
+ upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))
264
+
265
+ # Find all high correlation feature pairs
266
+ high_corr_pairs = []
267
+ for i, col1 in enumerate(upper.columns):
268
+ for col2 in upper.columns[i+1:]:
269
+ corr_val = upper.loc[col1, col2]
270
+ if pd.notna(corr_val) and corr_val > threshold:
271
+ high_corr_pairs.append((col1, col2, corr_val))
272
+
273
+ if not high_corr_pairs:
274
+ break
275
+
276
+ # For each high correlation feature pair, select the feature with smaller original gain as candidate for dropping
277
+ candidates = set()
278
+ for col1, col2, corr_val in high_corr_pairs:
279
+ # Skip top N kept features
280
+ if col1 in top_features and col2 in top_features:
281
+ continue
282
+
283
+ gain1 = gain_dict.get(col1, 0)
284
+ gain2 = gain_dict.get(col2, 0)
285
+
286
+ # Select feature with smaller original gain
287
+ if gain1 <= gain2:
288
+ candidates.add(col1)
289
+ else:
290
+ candidates.add(col2)
291
+
292
+ if not candidates:
293
+ break
294
+
295
+ # Select feature with smallest original gain among candidates for dropping
296
+ candidates_list = list(candidates)
297
+ candidates_with_gain = [(c, gain_dict.get(c, 0)) for c in candidates_list]
298
+ candidates_with_gain.sort(key=lambda x: x[1])
299
+ to_drop = candidates_with_gain[0][0]
300
+
301
+ # Find all features highly correlated with this feature
302
+ related_vars = []
303
+ for col1, col2, corr_val in high_corr_pairs:
304
+ if col1 == to_drop:
305
+ related_vars.append((col2, corr_val))
306
+ elif col2 == to_drop:
307
+ related_vars.append((col1, corr_val))
308
+
309
+ # Record drop information
310
+ # Related variables column: show feature name and similarity value (correlation value)
311
+ related_str = ','.join([f"{v}(similarity={c:.4f})" for v, c in related_vars])
312
+ # Removal condition column: show related features and their corresponding gain values
313
+ gain_str = ','.join([f"{v}(gain={gain_dict.get(v, 0):.2f})" for v, c in related_vars])
314
+ dropped_info.append({
315
+ '变量': to_drop,
316
+ '原始gain': gain_dict.get(to_drop, 0),
317
+ '原始gain排名': rank_dict.get(to_drop, '-'),
318
+ '相关变量': related_str,
319
+ '去除条件': gain_str
320
+ })
321
+
322
+ # Delete this feature from data
323
+ data = data.drop(columns=[to_drop], errors='ignore')
324
+ current_features.remove(to_drop)
325
+
326
+ print(f" Dropped feature: {to_drop} (original gain={gain_dict.get(to_drop, 0):.2f})")
327
+
328
+ # Convert to DataFrame and sort by original gain in descending order
329
+ dropped_df = pd.DataFrame(dropped_info)
330
+ if len(dropped_df) > 0:
331
+ dropped_df = dropped_df.sort_values('原始gain', ascending=False)
332
+ dropped_df = dropped_df.reset_index(drop=True)
333
+
334
+ return data, dropped_df
335
+
336
+
337
+ def drop_highnoise_features(data: pd.DataFrame, features: List[str],
338
+ n_estimators: int = 100, max_depth: int = 5, gain_threshold: float = 50) -> tuple:
339
+ """Null Importance to remove high noise features"""
340
+ # Check if feature list is empty
341
+ if len(features) == 0:
342
+ print(" No features to process")
343
+ return data, pd.DataFrame(columns=['变量', '原始gain', '反转后gain'])
344
+
345
+ # Check if data is sufficient
346
+ if len(data) < 1000:
347
+ print(f" Insufficient data ({len(data)} rows), skip Null Importance")
348
+ return data, pd.DataFrame(columns=['变量', '原始gain', '反转后gain'])
349
+
350
+ X = data[features].copy()
351
+ Y = data['new_target'].copy()
352
+
353
+ # Check if X is empty or contains NaN
354
+ if X.shape[1] == 0:
355
+ print(" Feature data is empty, skip Null Importance")
356
+ return data, pd.DataFrame(columns=['变量', '原始gain', '反转后gain'])
357
+
358
+ # Fill NaN
359
+ X = X.fillna(0)
360
+
361
+ # Shuffle labels
362
+ Y_permuted = Y.copy()
363
+ for _ in range(20):
364
+ Y_permuted = np.random.permutation(Y_permuted)
365
+
366
+ clf = lgb.LGBMClassifier(
367
+ objective='binary', boosting_type='gbdt', learning_rate=0.05,
368
+ max_depth=max_depth, min_child_samples=2000, min_child_weight=20,
369
+ n_estimators=n_estimators, num_leaves=2**max_depth - 1, n_jobs=-1, verbose=-1
370
+ )
371
+
372
+ clf_permuted = lgb.LGBMClassifier(
373
+ objective='binary', boosting_type='gbdt', learning_rate=0.05,
374
+ max_depth=max_depth, min_child_samples=2000, min_child_weight=20,
375
+ n_estimators=n_estimators, num_leaves=2**max_depth - 1, n_jobs=-1, verbose=-1
376
+ )
377
+
378
+ results, results_permuted = [], []
379
+
380
+ print("Null Importance calculation in progress...")
381
+ for i in range(2):
382
+ random_n = np.random.randint(30)
383
+
384
+ X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=random_n)
385
+
386
+ # Check if training data is valid
387
+ if X_train.shape[0] == 0 or X_test.shape[0] == 0:
388
+ print(f" Round {i+1}: Data split failed, skip")
389
+ continue
390
+
391
+ clf.fit(X_train, y_train)
392
+
393
+ X_train_, X_test_, y_train_, y_test_ = train_test_split(X, Y_permuted, test_size=0.3, random_state=random_n)
394
+
395
+ if X_train_.shape[0] == 0 or X_test_.shape[0] == 0:
396
+ print(f" Round {i+1}: Shuffled data split failed, skip")
397
+ continue
398
+
399
+ clf_permuted.fit(X_train_, y_train_)
400
+
401
+ imp_real = pd.DataFrame({
402
+ 'feature': clf.booster_.feature_name(),
403
+ 'gain': clf.booster_.feature_importance(importance_type='gain')
404
+ })
405
+ imp_perm = pd.DataFrame({
406
+ 'feature': clf_permuted.booster_.feature_name(),
407
+ 'gain': clf_permuted.booster_.feature_importance(importance_type='gain')
408
+ })
409
+
410
+ results.append(imp_real)
411
+ results_permuted.append(imp_perm)
412
+
413
+ train_auc = roc_auc_score(y_train, clf.predict_proba(X_train)[:, 1])
414
+ test_auc = roc_auc_score(y_test, clf.predict_proba(X_test)[:, 1])
415
+ print(f" Round {i+1}: train_auc={train_auc:.3f}, test_auc={test_auc:.3f}")
416
+
417
+ # Check if there are valid results
418
+ if len(results) == 0 or len(results_permuted) == 0:
419
+ print(" No valid training results, skip Null Importance")
420
+ return data, pd.DataFrame(columns=['变量', '原始gain', '反转后gain'])
421
+
422
+ imp_real_avg = pd.concat(results).groupby('feature')['gain'].mean().reset_index()
423
+ imp_perm_avg = pd.concat(results_permuted).groupby('feature')['gain'].mean().reset_index()
424
+
425
+ comparison = imp_real_avg.merge(imp_perm_avg, on='feature', suffixes=('_real', '_perm'))
426
+ comparison['gain_real'] = comparison['gain_real'].fillna(0)
427
+ comparison['gain_perm'] = comparison['gain_perm'].fillna(0)
428
+
429
+ # Use condition where absolute difference of gain values before and after permutation is less than 50
430
+ comparison['gain_diff'] = (comparison['gain_real'] - comparison['gain_perm']).abs()
431
+ noise_features = comparison[comparison['gain_diff'] < gain_threshold]['feature'].tolist()
432
+
433
+ # List original gain and permuted gain for all features
434
+ dropped_info = pd.DataFrame({
435
+ '变量': comparison['feature'].values,
436
+ '原始gain': comparison['gain_real'].values,
437
+ '反转后gain': comparison['gain_perm'].values
438
+ })
439
+ # Add status column, mark dropped features as '去除', kept features as '保留'
440
+ dropped_info['状态'] = dropped_info.apply(
441
+ lambda x: '去除' if np.abs(x['原始gain'] - x['反转后gain']) < gain_threshold else '保留', axis=1
442
+ )
443
+ # Sort by original gain in descending order
444
+ dropped_info = dropped_info.sort_values('原始gain', ascending=False)
445
+ dropped_info = dropped_info.reset_index(drop=True)
446
+ # Add original gain ranking column
447
+ dropped_info['原始gain排名'] = range(1, len(dropped_info) + 1)
448
+
449
+ data = data.drop(columns=[c for c in noise_features if c in data.columns])
450
+
451
+ print(f" Dropped {len(noise_features)} noise features")
452
+ return data, dropped_info
453
+
454
+
455
+ def _calc_single_psi(args):
456
+ """Calculate PSI for a single organization and single feature - NaN as separate bin"""
457
+ org, train_month, test_month, train_n, test_n, f, data_ref, min_sample = args
458
+
459
+ try:
460
+ org_data = data_ref[data_ref['new_org'] == org]
461
+ train_data = org_data[org_data['new_date_ym'] == train_month]
462
+ test_data = org_data[org_data['new_date_ym'] == test_month]
463
+
464
+ # Get data
465
+ train_vals = train_data[f].values
466
+ test_vals = test_data[f].values
467
+
468
+ # Mark NaN
469
+ train_nan_mask = pd.isna(train_vals)
470
+ test_nan_mask = pd.isna(test_vals)
471
+
472
+ # Non-NaN values for binning
473
+ train_nonan = train_vals[~train_nan_mask]
474
+ test_nonan = test_vals[~test_nan_mask]
475
+
476
+ if len(train_nonan) < min_sample or len(test_nonan) < min_sample:
477
+ return {
478
+ '机构': org, '日期': f"{train_month}->{test_month}",
479
+ '变量': f, 'PSI': None, '有效计算': 0,
480
+ '样本数': train_n
481
+ }
482
+
483
+ # Bin based on non-NaN data (10 bins)
484
+ try:
485
+ bins = pd.qcut(train_nonan, q=10, duplicates='drop', retbins=True)[1]
486
+ except:
487
+ bins = pd.cut(train_nonan, bins=10, retbins=True)[1]
488
+
489
+ # Calculate proportion of each bin (including NaN bin)
490
+ train_counts = []
491
+ test_counts = []
492
+
493
+ for i in range(len(bins)):
494
+ if i == 0:
495
+ train_counts.append((~train_nan_mask & (train_vals <= bins[i])).sum())
496
+ test_counts.append((~test_nan_mask & (test_vals <= bins[i])).sum())
497
+ else:
498
+ train_counts.append((~train_nan_mask & (train_vals > bins[i-1]) & (train_vals <= bins[i])).sum())
499
+ test_counts.append((~test_nan_mask & (test_vals > bins[i-1]) & (test_vals <= bins[i])).sum())
500
+
501
+ # NaN bin
502
+ train_counts.append(train_nan_mask.sum())
503
+ test_counts.append(test_nan_mask.sum())
504
+
505
+ # Convert to proportions
506
+ train_pct = np.array(train_counts) / len(train_vals)
507
+ test_pct = np.array(test_counts) / len(test_vals)
508
+
509
+ # Avoid 0 values
510
+ train_pct = np.where(train_pct == 0, 1e-6, train_pct)
511
+ test_pct = np.where(test_pct == 0, 1e-6, test_pct)
512
+
513
+ # Calculate PSI
514
+ psi = np.sum((test_pct - train_pct) * np.log(test_pct / train_pct))
515
+
516
+ return {
517
+ '机构': org, '日期': f"{train_month}->{test_month}",
518
+ '变量': f, 'PSI': round(psi, 4), '有效计算': 1,
519
+ '样本数': train_n
520
+ }
521
+ except Exception as e:
522
+ return {
523
+ '机构': org, '日期': f"{train_month}->{test_month}",
524
+ '变量': f, 'PSI': None, '有效计算': 0,
525
+ '样本数': train_n
526
+ }
527
+
528
+
529
+ def drop_highpsi_features(data: pd.DataFrame, features: List[str],
530
+ psi_threshold: float = 0.1, max_months_ratio: float = 1/3,
531
+ max_orgs: int = 4, min_sample_per_month: int = 100, n_jobs: int = 4) -> tuple:
532
+ """Drop high PSI features - by organization + month-by-month version
533
+
534
+ Multi-processing at feature level, loop through organizations, parallel calculation of features within organizations
535
+
536
+ Args:
537
+ psi_threshold: PSI threshold, values above this are considered unstable
538
+ max_months_ratio: Maximum tolerated month ratio, if more than this ratio of months have PSI above threshold, record in processing table
539
+ max_orgs: Maximum tolerated organization count, if more than this number of organizations are unstable, record in processing table
540
+ min_sample_per_month: Minimum sample count per month
541
+
542
+ Returns:
543
+ data: Data after dropping
544
+ psi_detail: PSI details (PSI value of each feature in each organization each month)
545
+ psi_process: PSI processing table (features that do not meet the conditions)
546
+ """
547
+ orgs = data['new_org'].unique()
548
+
549
+ # Build task list: each organization, each pair of months, each feature
550
+ tasks = []
551
+ for org in orgs:
552
+ org_data = data[data['new_org'] == org]
553
+ months = sorted(org_data['new_date_ym'].unique())
554
+
555
+ if len(months) < 2:
556
+ continue
557
+
558
+ for i in range(len(months) - 1):
559
+ train_month = months[i]
560
+ test_month = months[i + 1]
561
+
562
+ train_data = org_data[org_data['new_date_ym'] == train_month]
563
+ test_data = org_data[org_data['new_date_ym'] == test_month]
564
+
565
+ train_n = len(train_data)
566
+ test_n = len(test_data)
567
+
568
+ for f in features:
569
+ tasks.append((org, train_month, test_month, train_n, test_n, f, data, min_sample_per_month))
570
+
571
+ # Multi-process PSI calculation (parallel at feature level)
572
+ print(f" PSI calculation: {len(tasks)} tasks, using {n_jobs} processes")
573
+ results = Parallel(n_jobs=n_jobs, verbose=0)(delayed(_calc_single_psi)(task) for task in tasks)
574
+
575
+ psi_df = pd.DataFrame(results)
576
+
577
+ if len(psi_df) == 0:
578
+ return data, pd.DataFrame(columns=['变量', '机构', '月份', 'PSI值']), pd.DataFrame(columns=['变量', '处理原因'])
579
+
580
+ # Filter valid calculation records
581
+ valid_psi = psi_df[psi_df['有效计算'] == 1].copy()
582
+
583
+ if len(valid_psi) == 0:
584
+ return data, pd.DataFrame(columns=['变量', '机构', '月份', 'PSI值']), pd.DataFrame(columns=['变量', '处理原因'])
585
+
586
+ # PSI detail table: PSI value of each feature in each organization each month
587
+ # Change date to single month, initial month PSI value is 0
588
+ psi_detail = valid_psi[['机构', '日期', '变量', 'PSI']].copy()
589
+
590
+ # Parse date, extract test month
591
+ psi_detail['月份'] = psi_detail['日期'].apply(lambda x: x.split('->')[1] if '->' in x else x)
592
+ psi_detail = psi_detail.rename(columns={'PSI': 'PSI值'})
593
+
594
+ # Sort by feature, organization, month in ascending order
595
+ psi_detail = psi_detail.sort_values(['变量', '机构', '月份'], ascending=[True, True, True])
596
+
597
+ # Get all organizations and months
598
+ all_orgs = sorted(psi_detail['机构'].unique())
599
+ all_vars = sorted(psi_detail['变量'].unique())
600
+
601
+ # Build complete PSI detail table (including initial month, PSI value is 0)
602
+ psi_detail_list = []
603
+ for org in all_orgs:
604
+ org_data = psi_detail[psi_detail['机构'] == org]
605
+ if len(org_data) == 0:
606
+ continue
607
+
608
+ # Get all months for this organization
609
+ months = sorted(org_data['月份'].unique())
610
+
611
+ for var in all_vars:
612
+ var_data = org_data[org_data['变量'] == var]
613
+ if len(var_data) == 0:
614
+ continue
615
+
616
+ # Initial month PSI value is 0
617
+ psi_detail_list.append({
618
+ '机构': org,
619
+ '变量': var,
620
+ '月份': months[0],
621
+ 'PSI值': 0.0
622
+ })
623
+
624
+ # Subsequent months PSI values are calculation results
625
+ for i in range(1, len(months)):
626
+ month = months[i]
627
+ var_month_data = var_data[var_data['月份'] == month]
628
+ if len(var_month_data) > 0:
629
+ psi_value = var_month_data['PSI值'].values[0]
630
+ else:
631
+ psi_value = 0.0
632
+ psi_detail_list.append({
633
+ '机构': org,
634
+ '变量': var,
635
+ '月份': month,
636
+ 'PSI值': psi_value
637
+ })
638
+
639
+ psi_detail = pd.DataFrame(psi_detail_list)
640
+ psi_detail = psi_detail[['机构', '变量', '月份', 'PSI值']]
641
+ psi_detail = psi_detail.reset_index(drop=True)
642
+ # Sort by feature, organization, month in ascending order
643
+ psi_detail = psi_detail.sort_values(['变量', '机构', '月份'], ascending=[True, True, True])
644
+ psi_detail = psi_detail.reset_index(drop=True)
645
+
646
+ # Mark unstable
647
+ valid_psi['不稳定'] = (valid_psi['PSI'] > psi_threshold).astype(int)
648
+
649
+ # Summary: number of unstable months and total months for each organization each feature
650
+ org_summary = valid_psi.groupby(['机构', '变量']).agg(
651
+ 不稳定月份数=('不稳定', 'sum'),
652
+ 总月份数=('变量', 'count')
653
+ ).reset_index()
654
+
655
+ # Mark whether each organization each feature is unstable
656
+ # Ensure threshold is at least 1, avoid being too strict when organization has few months
657
+ org_summary['不稳定阈值'] = org_summary['总月份数'].apply(
658
+ lambda x: max(1, int(x * max_months_ratio))
659
+ )
660
+ org_summary['是否不稳定'] = org_summary['不稳定月份数'] >= org_summary['不稳定阈值']
661
+
662
+ # Organization level summary: number of unstable organizations
663
+ org_count = len(orgs)
664
+ channel_summary = org_summary.groupby('变量').apply(
665
+ lambda x: pd.Series({
666
+ '机构数': org_count,
667
+ '不稳定机构数': x['是否不稳定'].sum()
668
+ })
669
+ ).reset_index()
670
+
671
+ # Mark features that need processing
672
+ channel_summary['需处理'] = channel_summary['不稳定机构数'] >= max_orgs
673
+ channel_summary['处理原因'] = channel_summary.apply(
674
+ lambda x: f'PSI unstable in {x["不稳定机构数"]} organizations' if x['需处理'] else '', axis=1
675
+ )
676
+
677
+ # Get list of unstable organizations for each feature
678
+ unstable_orgs_dict = {}
679
+ for var in org_summary['变量'].unique():
680
+ var_orgs = org_summary[(org_summary['变量'] == var) & (org_summary['是否不稳定'] == True)]['机构'].tolist()
681
+ unstable_orgs_dict[var] = var_orgs
682
+
683
+ # PSI processing table: features that do not meet the conditions
684
+ psi_process = channel_summary[channel_summary['需处理']].copy()
685
+ psi_process['不稳定机构'] = psi_process['变量'].apply(lambda x: ','.join(unstable_orgs_dict.get(x, [])))
686
+ psi_process = psi_process[['变量', '处理原因', '不稳定机构']]
687
+ psi_process = psi_process.reset_index(drop=True)
688
+
689
+ # Filter features to drop
690
+ if len(psi_process) > 0 and '变量' in psi_process.columns:
691
+ to_drop_vars = psi_process['变量'].tolist()
692
+ data = data.drop(columns=[c for c in to_drop_vars if c in data.columns])
693
+
694
+ return data, psi_detail, psi_process
695
+
696
+
697
+ def iv_distribution_by_org(iv_detail: pd.DataFrame, oos_orgs: list = None, iv_bins: list = [0, 0.02, 0.05, 0.1, float('inf')]) -> pd.DataFrame:
698
+ """Count number and proportion of features in different IV ranges for each organization
699
+
700
+ Args:
701
+ iv_detail: IV detail table (containing feature, overall, organization columns)
702
+ oos_orgs: Out-of-sample organization list
703
+ iv_bins: IV range boundaries [0, 0.02, 0.05, 0.1, inf]
704
+
705
+ Returns:
706
+ IV distribution statistics table
707
+ """
708
+ if oos_orgs is None:
709
+ oos_orgs = []
710
+
711
+ # Get organization columns (exclude '变量' and '整体' columns)
712
+ org_cols = [c for c in iv_detail.columns if c not in ['变量', '整体']]
713
+
714
+ # Define range labels
715
+ bin_labels = ['[0, 0.02)', '[0.02, 0.05)', '[0.05, 0.1)', '[0.1, +∞)']
716
+
717
+ result = []
718
+
719
+ # Statistics for each organization (not including overall)
720
+ for org in org_cols:
721
+ org_iv = iv_detail[org].dropna()
722
+ total_vars = len(org_iv)
723
+
724
+ # Determine organization type
725
+ org_type = '贷外' if org in oos_orgs else '建模'
726
+
727
+ for i in range(len(iv_bins) - 1):
728
+ lower = iv_bins[i]
729
+ upper = iv_bins[i + 1]
730
+ if upper == float('inf'):
731
+ count = ((org_iv >= lower)).sum()
732
+ else:
733
+ count = ((org_iv >= lower) & (org_iv < upper)).sum()
734
+ ratio = count / total_vars if total_vars > 0 else 0
735
+ result.append({
736
+ '机构': org,
737
+ '类型': org_type,
738
+ 'IV区间': bin_labels[i],
739
+ '变量个数': count,
740
+ '占比': f'{ratio:.2%}'
741
+ })
742
+
743
+ return pd.DataFrame(result)
744
+
745
+
746
+ def psi_distribution_by_org(psi_detail: pd.DataFrame, oos_orgs: list = None, psi_bins: list = [0, 0.05, 0.1, float('inf')]) -> pd.DataFrame:
747
+ """Count number and proportion of features in different PSI ranges for each organization
748
+
749
+ Args:
750
+ psi_detail: PSI detail table (containing organization, feature, month, PSI value columns)
751
+ oos_orgs: Out-of-sample organization list
752
+ psi_bins: PSI range boundaries [0, 0.05, 0.1, inf]
753
+
754
+ Returns:
755
+ PSI distribution statistics table
756
+ """
757
+ if oos_orgs is None:
758
+ oos_orgs = []
759
+
760
+ # Define range labels
761
+ bin_labels = ['[0, 0.05)', '[0.05, 0.1)', '[0.1, +∞)']
762
+
763
+ result = []
764
+
765
+ # Get all organizations
766
+ orgs = psi_detail['机构'].unique()
767
+
768
+ for org in orgs:
769
+ org_data = psi_detail[psi_detail['机构'] == org]
770
+
771
+ # Determine organization type
772
+ org_type = '贷外' if org in oos_orgs else '建模'
773
+
774
+ # For each feature, take its maximum PSI value
775
+ var_max_psi = org_data.groupby('变量')['PSI值'].max()
776
+ total_vars = len(var_max_psi)
777
+
778
+ for i in range(len(psi_bins) - 1):
779
+ lower = psi_bins[i]
780
+ upper = psi_bins[i + 1]
781
+ if upper == float('inf'):
782
+ count = ((var_max_psi >= lower)).sum()
783
+ else:
784
+ count = ((var_max_psi >= lower) & (var_max_psi < upper)).sum()
785
+ ratio = count / total_vars if total_vars > 0 else 0
786
+ result.append({
787
+ '机构': org,
788
+ '类型': org_type,
789
+ 'PSI区间': bin_labels[i],
790
+ '变量个数': count,
791
+ '占比': f'{ratio:.2%}'
792
+ })
793
+
794
+ return pd.DataFrame(result)
795
+
796
+
797
+ def value_ratio_distribution_by_org(data: pd.DataFrame, features: List[str],
798
+ oos_orgs: list = None,
799
+ value_bins: list = [0, 0.15, 0.35, 0.65, 0.95, 1.0]) -> pd.DataFrame:
800
+ """Count number and proportion of features in different value ratio ranges for each organization
801
+
802
+ Args:
803
+ data: Data (containing new_org column)
804
+ features: Feature list
805
+ oos_orgs: Out-of-sample organization list
806
+ value_bins: Value ratio range boundaries [0, 0.15, 0.35, 0.65, 0.95, 1.0]
807
+
808
+ Returns:
809
+ Value ratio distribution statistics table
810
+ """
811
+ if oos_orgs is None:
812
+ oos_orgs = []
813
+
814
+ # Define range labels
815
+ bin_labels = ['[0, 15%)', '[15%, 35%)', '[35%, 65%)', '[65%, 95%)', '[95%, 100%]']
816
+
817
+ result = []
818
+
819
+ # Get all organizations
820
+ orgs = data['new_org'].unique()
821
+
822
+ for org in orgs:
823
+ org_data = data[data['new_org'] == org]
824
+
825
+ # Determine organization type
826
+ org_type = '贷外' if org in oos_orgs else '建模'
827
+
828
+ # Calculate value ratio for each feature (proportion of non-NaN)
829
+ value_ratios = {}
830
+ for f in features:
831
+ if f in org_data.columns:
832
+ non_null_count = org_data[f].notna().sum()
833
+ total_count = len(org_data)
834
+ value_ratios[f] = non_null_count / total_count if total_count > 0 else 0
835
+
836
+ # Count number of features in each range
837
+ total_vars = len(value_ratios)
838
+ for i in range(len(value_bins) - 1):
839
+ lower = value_bins[i]
840
+ upper = value_bins[i + 1]
841
+ if upper == 1.0:
842
+ count = sum(1 for v in value_ratios.values() if lower <= v <= upper)
843
+ else:
844
+ count = sum(1 for v in value_ratios.values() if lower <= v < upper)
845
+ ratio = count / total_vars if total_vars > 0 else 0
846
+ result.append({
847
+ '机构': org,
848
+ '类型': org_type,
849
+ '有值率区间': bin_labels[i],
850
+ '变量个数': count,
851
+ '占比': f'{ratio:.2%}'
852
+ })
853
+
854
+ return pd.DataFrame(result)
855
+
856
+
857
+ def calculate_iv_by_org(data: pd.DataFrame, features: List[str],
858
+ n_jobs: int = 4) -> Tuple[pd.DataFrame, pd.DataFrame]:
859
+ """Calculate IV by organization and overall
860
+
861
+ Returns:
862
+ iv_by_org: IV details by organization
863
+ iv_overall: Overall IV
864
+ """
865
+ from references.func import calculate_iv
866
+
867
+ orgs = data['new_org'].unique()
868
+
869
+ # Overall IV
870
+ iv_overall = calculate_iv(data, features, n_jobs=n_jobs)
871
+ iv_overall['类型'] = '整体'
872
+
873
+ # IV by organization
874
+ iv_by_org = []
875
+ for org in orgs:
876
+ org_data = data[data['new_org'] == org]
877
+ org_iv = calculate_iv(org_data, features, n_jobs=1) # Single process for single organization
878
+ if len(org_iv) > 0: # Only add non-empty results
879
+ org_iv['机构'] = org
880
+ org_iv['类型'] = '分机构'
881
+ iv_by_org.append(org_iv)
882
+
883
+ iv_by_org = pd.concat(iv_by_org, ignore_index=True) if iv_by_org else pd.DataFrame(columns=['变量', 'IV', '机构', '类型'])
884
+
885
+ return iv_by_org, iv_overall
886
+
887
+
888
+ def calculate_psi_detail(data: pd.DataFrame, features: List[str],
889
+ max_psi: float = 0.1, min_months_unstable: int = 3,
890
+ min_sample: int = 100, n_jobs: int = 4) -> tuple:
891
+ """Calculate month-by-month PSI details for each feature in each organization, and mark whether to drop
892
+
893
+ Returns:
894
+ data: Data after dropping
895
+ dropped: Summary of dropped features
896
+ psi_summary: Complete PSI details (including drop flag)
897
+ """
898
+ orgs = data['new_org'].unique()
899
+
900
+ # Build tasks
901
+ tasks = []
902
+ for org in orgs:
903
+ org_data = data[data['new_org'] == org]
904
+ months = sorted(org_data['new_date_ym'].unique())
905
+
906
+ if len(months) < 2:
907
+ continue
908
+
909
+ for i in range(len(months) - 1):
910
+ train_month = months[i]
911
+ test_month = months[i + 1]
912
+
913
+ train_data = org_data[org_data['new_date_ym'] == train_month]
914
+ test_data = org_data[org_data['new_date_ym'] == test_month]
915
+
916
+ train_n = len(train_data)
917
+ test_n = len(test_data)
918
+
919
+ for f in features:
920
+ tasks.append((org, train_month, test_month, train_n, test_n, f, data, min_sample))
921
+
922
+ # Multi-process calculation
923
+ print(f" PSI calculation: {len(tasks)} tasks, using {n_jobs} processes")
924
+ results = Parallel(n_jobs=n_jobs, verbose=0)(delayed(_calc_single_psi)(task) for task in tasks)
925
+
926
+ psi_df = pd.DataFrame(results)
927
+
928
+ if len(psi_df) == 0:
929
+ return data, pd.DataFrame(columns=['变量', '机构数', '不稳定机构数', '原因']), pd.DataFrame(columns=['变量', '机构数', '不稳定机构数', '是否剔除', '去除条件'])
930
+
931
+ # Filter valid calculation records
932
+ valid_psi = psi_df[psi_df['有效计算'] == 1].copy()
933
+
934
+ if len(valid_psi) == 0:
935
+ return data, pd.DataFrame(columns=['变量', '机构数', '不稳定机构数', '原因']), pd.DataFrame(columns=['变量', '机构数', '不稳定机构数', '是否剔除', '去除条件'])
936
+
937
+ # Mark unstable
938
+ valid_psi['不稳定'] = (valid_psi['PSI'] > max_psi).astype(int)
939
+
940
+ # Summary: number of unstable months for each organization each feature
941
+ org_summary = valid_psi.groupby(['机构', '变量'])['不稳定'].sum().reset_index()
942
+ org_summary.columns = ['机构', '变量', '不稳定月份数']
943
+
944
+ # Organization level summary: features with more than min_months_unstable unstable months
945
+ org_count = len(orgs)
946
+ channel_summary = org_summary.groupby('变量').apply(
947
+ lambda x: pd.Series({
948
+ '机构数': org_count,
949
+ '不稳定机构数': (x['不稳定月份数'] >= min_months_unstable).sum()
950
+ })
951
+ ).reset_index()
952
+
953
+ # Mark features that need to be dropped (more than 1/3 organizations unstable)
954
+ channel_summary['需剔除'] = channel_summary['不稳定机构数'] > (channel_summary['机构数'] / 3)
955
+ channel_summary['是否剔除'] = channel_summary['需剔除'].astype(int)
956
+ channel_summary['去除条件'] = channel_summary.apply(
957
+ lambda x: f'More than 1/3 of {org_count} organizations have PSI>{max_psi} for {min_months_unstable} consecutive months' if x['需剔除'] else '', axis=1
958
+ )
959
+
960
+ # Filter features to drop
961
+ if len(channel_summary) > 0 and '变量' in channel_summary.columns:
962
+ to_drop_vars = channel_summary[channel_summary['需剔除']]['变量'].tolist()
963
+ data = data.drop(columns=[c for c in to_drop_vars if c in data.columns])
964
+
965
+ # Organize drop information (only return dropped features)
966
+ dropped = channel_summary[channel_summary['需剔除']].copy()
967
+ dropped['原因'] = f'More than 1/3 of {org_count} organizations have PSI>{max_psi} for {min_months_unstable} consecutive months'
968
+
969
+ return data, dropped[['变量', '机构数', '不稳定机构数', '原因']], channel_summary[['变量', '机构数', '不稳定机构数', '是否剔除', '去除条件']]
970
+
971
+
972
+ def export_cleaning_report(filepath: str, steps: list,
973
+ iv_detail: pd.DataFrame = None,
974
+ iv_process: pd.DataFrame = None,
975
+ psi_detail: pd.DataFrame = None,
976
+ psi_process: pd.DataFrame = None,
977
+ params: dict = None,
978
+ iv_distribution: pd.DataFrame = None,
979
+ psi_distribution: pd.DataFrame = None,
980
+ value_ratio_distribution: pd.DataFrame = None):
981
+ """Export cleaning report to xlsx - one sheet per step
982
+
983
+ Args:
984
+ filepath: Output path
985
+ steps: Cleaning step list [(step name, DataFrame), ...]
986
+ iv_detail: IV details (IV value of each feature in each organization and overall)
987
+ iv_process: IV processing table (features that do not meet the conditions)
988
+ psi_detail: PSI details (PSI value of each feature in each organization each month)
989
+ psi_process: PSI processing table (features that do not meet the conditions)
990
+ params: Hyperparameter dictionary, used to dynamically generate conditions
991
+ iv_distribution: IV distribution statistics table
992
+ psi_distribution: PSI distribution statistics table
993
+ value_ratio_distribution: Value ratio distribution statistics table
994
+ """
995
+ from openpyxl import load_workbook
996
+
997
+ try:
998
+ wb = load_workbook(filepath)
999
+ except:
1000
+ wb = Workbook()
1001
+ wb.remove(wb.active)
1002
+
1003
+ # Summary sheet - only show real filtering steps
1004
+ if '汇总' in wb.sheetnames:
1005
+ del wb['汇总']
1006
+ ws = wb.create_sheet('汇总', 0)
1007
+ ws['A1'] = 'Data Cleaning Report'
1008
+ ws['A2'] = f'Generated at: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}'
1009
+ ws['A4'] = 'Step'
1010
+ ws['B4'] = 'Operation Details'
1011
+ ws['C4'] = 'Operation Result'
1012
+ ws['D4'] = 'Condition'
1013
+
1014
+ # Only show real filtering steps (excluding details and distribution statistics)
1015
+ filter_steps = [
1016
+ 'Step4-异常月份处理', 'Step6-高缺失率处理', 'Step7-IV处理',
1017
+ 'Step8-PSI处理', 'Step9-null importance处理', 'Step10-高相关性剔除'
1018
+ ]
1019
+
1020
+ # Steps to exclude (details and distribution statistics)
1021
+ exclude_steps = [
1022
+ 'Step7-IV明细', 'Step7-IV分布统计', 'Step8-PSI明细',
1023
+ 'Step8-PSI分布统计', 'Step5-有值率分布统计'
1024
+ ]
1025
+
1026
+ # Steps that need to show drop count
1027
+ show_drop_count_steps = ['分离OOS数据']
1028
+
1029
+ # Steps that only show parameter standards (no operation result)
1030
+ show_param_only_steps = ['机构样本统计', '缺失率明细']
1031
+
1032
+ # Add note: each step is executed independently
1033
+ ws['A3'] = 'Note: Each filtering step is executed independently, data is not deleted, only statistics of features that do not meet conditions are recorded'
1034
+
1035
+ # Get parameters, use default values if not provided
1036
+ if params is None:
1037
+ params = {}
1038
+
1039
+ min_ym_bad_sample = params.get('min_ym_bad_sample', 10)
1040
+ min_ym_sample = params.get('min_ym_sample', 500)
1041
+ missing_ratio = params.get('missing_ratio', 0.6)
1042
+ overall_iv_threshold = params.get('overall_iv_threshold', 0.1)
1043
+ org_iv_threshold = params.get('org_iv_threshold', 0.1)
1044
+ max_org_threshold = params.get('max_org_threshold', 2)
1045
+ psi_threshold = params.get('psi_threshold', 0.1)
1046
+ max_months_ratio = params.get('max_months_ratio', 1/3)
1047
+ max_orgs = params.get('max_orgs', 4)
1048
+ gain_threshold = params.get('gain_threshold', 50)
1049
+
1050
+ step_num = 1
1051
+ for name, df in steps:
1052
+ # Skip detail and distribution statistics steps
1053
+ if name in exclude_steps:
1054
+ continue
1055
+
1056
+ # Remove StepX- prefix from operation details
1057
+ display_name = name.replace('Step4-', '').replace('Step6-', '').replace('Step7-', '').replace('Step8-', '').replace('Step9-', '').replace('Step10-', '')
1058
+
1059
+ # Only show parameter standard steps (no operation result)
1060
+ if name in show_param_only_steps:
1061
+ ws.cell(4+step_num, 1, step_num)
1062
+ ws.cell(4+step_num, 2, display_name)
1063
+ result = ''
1064
+ # Condition: show parameter standards
1065
+ if name == '机构样本统计':
1066
+ condition = 'Statistics of sample count and bad sample rate for each organization'
1067
+ elif name == '缺失率明细':
1068
+ condition = 'Calculate missing rate for each feature'
1069
+ else:
1070
+ condition = ''
1071
+ ws.cell(4+step_num, 3, result)
1072
+ ws.cell(4+step_num, 4, condition)
1073
+ step_num += 1
1074
+ # Show steps that need to display drop count
1075
+ elif name in show_drop_count_steps:
1076
+ ws.cell(4+step_num, 1, step_num)
1077
+ ws.cell(4+step_num, 2, display_name)
1078
+ if df is not None and len(df) > 0:
1079
+ if name == '分离OOS数据':
1080
+ # Special handling: show OOS and modeling sample counts
1081
+ if '变量' in df.columns and '数量' in df.columns:
1082
+
1083
+ oos_count = df[df['变量'] == 'OOS样本']['数量'].values[0] if len(df[df['变量'] == 'OOS样本']) > 0 else 0
1084
+ model_count = df[df['变量'] == '建模样本']['数量'].values[0] if len(df[df['变量'] == '建模样本']) > 0 else 0
1085
+ result = f'OOS samples {oos_count}, modeling samples {model_count}'
1086
+ else:
1087
+ result = f'{len(df)} rows'
1088
+ elif '变量' in df.columns:
1089
+ result = f'Dropped {len(df)} features'
1090
+ else:
1091
+ result = f'Dropped {len(df)}'
1092
+ condition = ''
1093
+ else:
1094
+ result = 'Empty'
1095
+ condition = ''
1096
+ ws.cell(4+step_num, 3, result)
1097
+ ws.cell(4+step_num, 4, condition)
1098
+ step_num += 1
1099
+ elif name in filter_steps:
1100
+ ws.cell(4+step_num, 1, step_num)
1101
+ ws.cell(4+step_num, 2, display_name)
1102
+
1103
+ # Generate operation result and condition
1104
+ if df is not None and len(df) > 0:
1105
+ if name == 'Step4-异常月份处理':
1106
+ # Operation result: dropped months
1107
+ if '年月' in df.columns:
1108
+ result = 'Dropped ' + ','.join(df['年月'].astype(str).tolist())
1109
+ else:
1110
+ result = 'Dropped ' + ','.join(df.iloc[:, 0].astype(str).tolist())
1111
+ # Condition: parameter standards
1112
+ condition = f'Months with bad sample count less than {min_ym_bad_sample} or total sample count less than {min_ym_sample} will be dropped (independent execution)'
1113
+ elif name == 'Step6-高缺失率处理':
1114
+ # Operation result: number of dropped features
1115
+ if '变量' in df.columns:
1116
+ result = f'Dropped {len(df)} features'
1117
+ else:
1118
+ result = f'Dropped {len(df)}'
1119
+ # Condition: parameter standards
1120
+ condition = f'Features with overall missing rate greater than {missing_ratio} will be dropped (independent execution)'
1121
+ elif name == 'Step7-IV处理':
1122
+ # Operation result: number of dropped features
1123
+ if '变量' in df.columns:
1124
+ result = f'Dropped {len(df)} features'
1125
+ else:
1126
+ result = f'Dropped {len(df)}'
1127
+ # Condition: parameter standards
1128
+ condition = f'Features with overall IV less than {overall_iv_threshold} or IV less than {org_iv_threshold} in {max_org_threshold} or more organizations will be dropped (independent execution)'
1129
+ elif name == 'Step8-PSI处理':
1130
+ # Operation result: number of dropped features
1131
+ if '变量' in df.columns:
1132
+ result = f'Dropped {len(df)} features'
1133
+ else:
1134
+ result = f'Dropped {len(df)}'
1135
+ # Condition: parameter standards
1136
+ condition = f'PSI threshold {psi_threshold}, if an organization has more than {max_months_ratio:.0%} months with PSI greater than {psi_threshold}, the organization is considered unstable, if more than {max_orgs} organizations are unstable, the feature will be dropped (independent execution)'
1137
+ elif name == 'Step9-null importance处理':
1138
+ # Operation result: number of dropped features
1139
+ if '变量' in df.columns:
1140
+ result = f'Dropped {len(df[df["状态"]=="去除"])} features'
1141
+ else:
1142
+ result = f'Dropped {len(df)}'
1143
+ # Condition: parameter standards
1144
+ condition = f'Features with absolute difference of gain values before and after permutation less than {gain_threshold} will be identified as noise and dropped (independent execution)'
1145
+ elif name == 'Step10-高相关性剔除':
1146
+ # Operation result: number of dropped features
1147
+ if '变量' in df.columns:
1148
+ result = f'Dropped {len(df)} features'
1149
+ else:
1150
+ result = f'Dropped {len(df)}'
1151
+ # Condition: parameter standards
1152
+ max_corr = params.get('max_corr', 0.9)
1153
+ top_n_keep = params.get('top_n_keep', 20)
1154
+ condition = f'Features with correlation greater than {max_corr} will be dropped, keep top {top_n_keep} features by original gain ranking (independent execution)'
1155
+ else:
1156
+ result = 'Dropped ' + str(len(df))
1157
+ condition = ''
1158
+ else:
1159
+ result = 'Empty'
1160
+ condition = ''
1161
+
1162
+ ws.cell(4+step_num, 3, result)
1163
+ ws.cell(4+step_num, 4, condition)
1164
+ step_num += 1
1165
+
1166
+ # Calculate total number of dropped features (take union of dropped features from each step)
1167
+ all_dropped_vars = set()
1168
+ for name, df in steps:
1169
+ if name in filter_steps and df is not None and len(df) > 0 and '变量' in df.columns:
1170
+ if name == 'Step9-null importance处理':
1171
+ # null importance processing needs to filter features with status "去除"
1172
+ dropped_vars = df[df['状态'] == '去除']['变量'].tolist()
1173
+ else:
1174
+ dropped_vars = df['变量'].tolist()
1175
+ # Take union (deduplicated)
1176
+ all_dropped_vars = all_dropped_vars.union(set(dropped_vars))
1177
+
1178
+ # Add final statistics row
1179
+ final_step_num = step_num
1180
+ ws.cell(4+final_step_num, 1, final_step_num)
1181
+ ws.cell(4+final_step_num, 2, 'Final Dropped Features Statistics')
1182
+ ws.cell(4+final_step_num, 3, f'Total dropped {len(all_dropped_vars)} features (union of dropped features from each step)')
1183
+ ws.cell(4+final_step_num, 4, 'Each step is executed independently, final dropped features are the union of dropped features from each step')
1184
+
1185
+ # Details of each step (create sheets in step progression order)
1186
+ # Define sheet creation order
1187
+ sheet_order = [
1188
+ '机构样本统计', '分离OOS数据', 'Step4-异常月份处理', '缺失率明细',
1189
+ 'Step5-有值率分布统计', 'Step6-高缺失率处理', 'Step7-IV明细', 'Step7-IV处理',
1190
+ 'Step7-IV分布统计', 'Step8-PSI明细', 'Step8-PSI处理', 'Step8-PSI分布统计',
1191
+ 'Step9-null importance处理', 'Step10-高相关性剔除'
1192
+ ]
1193
+
1194
+ # Create sheets in order
1195
+ for sheet_name in sheet_order:
1196
+ # Find corresponding DataFrame in steps
1197
+ df = None
1198
+ for name, step_df in steps:
1199
+ if name == sheet_name:
1200
+ df = step_df
1201
+ break
1202
+
1203
+ if df is not None:
1204
+ if sheet_name in wb.sheetnames:
1205
+ del wb[sheet_name]
1206
+ ws_detail = wb.create_sheet(sheet_name)
1207
+
1208
+ for j, col in enumerate(df.columns):
1209
+ ws_detail.cell(1, j+1, col)
1210
+
1211
+ for i, row in df.iterrows():
1212
+ for j, val in enumerate(row):
1213
+ # Write value directly, avoid character escaping issues
1214
+ ws_detail.cell(i+2, j+1, val if val is not None else '')
1215
+
1216
+ header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
1217
+ header_font = Font(color="FFFFFF", bold=True)
1218
+ for cell in ws_detail[1]:
1219
+ cell.fill = header_fill
1220
+ cell.font = header_font
1221
+
1222
+ wb.save(filepath)
1223
+ print(f"Report saved: {filepath}")