cli-jaw 0.1.6 → 0.1.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 (746) hide show
  1. package/README.ko.md +68 -71
  2. package/README.md +123 -92
  3. package/README.zh-CN.md +68 -73
  4. package/dist/bin/cli-claw.js +96 -0
  5. package/dist/bin/cli-claw.js.map +1 -0
  6. package/dist/bin/cli-jaw.js +0 -0
  7. package/dist/bin/commands/doctor.js +3 -0
  8. package/dist/bin/commands/doctor.js.map +1 -1
  9. package/dist/bin/commands/init.js +36 -19
  10. package/dist/bin/commands/init.js.map +1 -1
  11. package/dist/bin/postinstall.js +175 -104
  12. package/dist/bin/postinstall.js.map +1 -1
  13. package/dist/lib/mcp-sync.js +43 -4
  14. package/dist/lib/mcp-sync.js.map +1 -1
  15. package/dist/server.js +22 -103
  16. package/dist/server.js.map +1 -1
  17. package/dist/src/cli/acp-client.js +1 -1
  18. package/dist/src/cli/command-context.js +73 -0
  19. package/dist/src/cli/command-context.js.map +1 -0
  20. package/dist/src/core/db.js +1 -1
  21. package/dist/src/memory/heartbeat.js +2 -1
  22. package/dist/src/memory/heartbeat.js.map +1 -1
  23. package/dist/src/orchestrator/collect.js +53 -0
  24. package/dist/src/orchestrator/collect.js.map +1 -0
  25. package/dist/src/orchestrator/gateway.js +49 -0
  26. package/dist/src/orchestrator/gateway.js.map +1 -0
  27. package/dist/src/telegram/bot.js +32 -119
  28. package/dist/src/telegram/bot.js.map +1 -1
  29. package/package.json +7 -7
  30. package/public/css/sidebar.css +14 -0
  31. package/public/dist/bundle.js +21 -21
  32. package/public/dist/bundle.js.map +3 -3
  33. package/public/index.html +2 -2
  34. package/public/js/features/settings.js +1 -2
  35. package/public/js/main.js +0 -1
  36. package/scripts/check-copilot-gap.js +57 -0
  37. package/scripts/check-deps-offline.mjs +75 -0
  38. package/scripts/check-deps-online.sh +26 -0
  39. package/scripts/i18n-registry.py +208 -0
  40. package/scripts/postinstall-guard.cjs +63 -0
  41. package/scripts/release.sh +30 -0
  42. package/skills_ref/1password/SKILL.md +0 -70
  43. package/skills_ref/agents-sdk/SKILL.md +0 -155
  44. package/skills_ref/agents-sdk/references/callable.md +0 -92
  45. package/skills_ref/agents-sdk/references/codemode.md +0 -207
  46. package/skills_ref/agents-sdk/references/email.md +0 -146
  47. package/skills_ref/agents-sdk/references/mcp.md +0 -154
  48. package/skills_ref/agents-sdk/references/state-scheduling.md +0 -164
  49. package/skills_ref/agents-sdk/references/streaming-chat.md +0 -178
  50. package/skills_ref/agents-sdk/references/workflows.md +0 -132
  51. package/skills_ref/algorithmic-art/LICENSE.txt +0 -202
  52. package/skills_ref/algorithmic-art/SKILL.md +0 -405
  53. package/skills_ref/algorithmic-art/templates/generator_template.js +0 -223
  54. package/skills_ref/algorithmic-art/templates/viewer.html +0 -599
  55. package/skills_ref/apple-notes/SKILL.md +0 -77
  56. package/skills_ref/apple-reminders/SKILL.md +0 -118
  57. package/skills_ref/atlas/SKILL.md +0 -99
  58. package/skills_ref/brainstorming/SKILL.md +0 -96
  59. package/skills_ref/browser/SKILL.md +0 -179
  60. package/skills_ref/canvas-design/LICENSE.txt +0 -202
  61. package/skills_ref/canvas-design/SKILL.md +0 -130
  62. package/skills_ref/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  63. package/skills_ref/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  64. package/skills_ref/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  65. package/skills_ref/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  66. package/skills_ref/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  67. package/skills_ref/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  68. package/skills_ref/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  69. package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  70. package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  71. package/skills_ref/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  72. package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  73. package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  74. package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  75. package/skills_ref/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  76. package/skills_ref/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  77. package/skills_ref/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  78. package/skills_ref/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  79. package/skills_ref/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  80. package/skills_ref/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  81. package/skills_ref/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  82. package/skills_ref/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  83. package/skills_ref/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  84. package/skills_ref/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  85. package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  86. package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  87. package/skills_ref/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  88. package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  89. package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  90. package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  91. package/skills_ref/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  92. package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  93. package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  94. package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  95. package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  96. package/skills_ref/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  97. package/skills_ref/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  98. package/skills_ref/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  99. package/skills_ref/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  100. package/skills_ref/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  101. package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  102. package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  103. package/skills_ref/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  104. package/skills_ref/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  105. package/skills_ref/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  106. package/skills_ref/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  107. package/skills_ref/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  108. package/skills_ref/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  109. package/skills_ref/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  110. package/skills_ref/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  111. package/skills_ref/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  112. package/skills_ref/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  113. package/skills_ref/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  114. package/skills_ref/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  115. package/skills_ref/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  116. package/skills_ref/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  117. package/skills_ref/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  118. package/skills_ref/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  119. package/skills_ref/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  120. package/skills_ref/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  121. package/skills_ref/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  122. package/skills_ref/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  123. package/skills_ref/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  124. package/skills_ref/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  125. package/skills_ref/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  126. package/skills_ref/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  127. package/skills_ref/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  128. package/skills_ref/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  129. package/skills_ref/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  130. package/skills_ref/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  131. package/skills_ref/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  132. package/skills_ref/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  133. package/skills_ref/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  134. package/skills_ref/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  135. package/skills_ref/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  136. package/skills_ref/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  137. package/skills_ref/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  138. package/skills_ref/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  139. package/skills_ref/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  140. package/skills_ref/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  141. package/skills_ref/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  142. package/skills_ref/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  143. package/skills_ref/changelog-generator/SKILL.md +0 -104
  144. package/skills_ref/cloudflare-deploy/SKILL.md +0 -207
  145. package/skills_ref/codebase-orientation/SKILL.md +0 -29
  146. package/skills_ref/config-file-explainer/SKILL.md +0 -26
  147. package/skills_ref/context-compression/SKILL.md +0 -265
  148. package/skills_ref/context-compression/references/evaluation-framework.md +0 -213
  149. package/skills_ref/context-compression/scripts/compression_evaluator.py +0 -658
  150. package/skills_ref/data-structure-chooser/SKILL.md +0 -26
  151. package/skills_ref/debugging-checklist/SKILL.md +0 -26
  152. package/skills_ref/debugging-helpers/CREATION-LOG.md +0 -119
  153. package/skills_ref/debugging-helpers/SKILL.md +0 -296
  154. package/skills_ref/debugging-helpers/condition-based-waiting-example.ts +0 -158
  155. package/skills_ref/debugging-helpers/condition-based-waiting.md +0 -115
  156. package/skills_ref/debugging-helpers/defense-in-depth.md +0 -122
  157. package/skills_ref/debugging-helpers/find-polluter.sh +0 -63
  158. package/skills_ref/debugging-helpers/root-cause-tracing.md +0 -169
  159. package/skills_ref/debugging-helpers/test-academic.md +0 -14
  160. package/skills_ref/debugging-helpers/test-pressure-1.md +0 -58
  161. package/skills_ref/debugging-helpers/test-pressure-2.md +0 -68
  162. package/skills_ref/debugging-helpers/test-pressure-3.md +0 -69
  163. package/skills_ref/deep-research/.env.example +0 -7
  164. package/skills_ref/deep-research/README.md +0 -246
  165. package/skills_ref/deep-research/SKILL.md +0 -106
  166. package/skills_ref/deep-research/requirements.txt +0 -2
  167. package/skills_ref/deep-research/scripts/research.py +0 -692
  168. package/skills_ref/dependency-install-helper/SKILL.md +0 -26
  169. package/skills_ref/dev/SKILL.md +0 -65
  170. package/skills_ref/dev-backend/SKILL.md +0 -61
  171. package/skills_ref/dev-data/SKILL.md +0 -76
  172. package/skills_ref/dev-frontend/LICENSE.txt +0 -177
  173. package/skills_ref/dev-frontend/SKILL.md +0 -42
  174. package/skills_ref/dev-testing/LICENSE.txt +0 -202
  175. package/skills_ref/dev-testing/SKILL.md +0 -96
  176. package/skills_ref/dev-testing/examples/console_logging.py +0 -35
  177. package/skills_ref/dev-testing/examples/element_discovery.py +0 -40
  178. package/skills_ref/dev-testing/examples/static_html_automation.py +0 -33
  179. package/skills_ref/dev-testing/scripts/with_server.py +0 -106
  180. package/skills_ref/develop-web-game/SKILL.md +0 -149
  181. package/skills_ref/differential-review/.claude-plugin/plugin.json +0 -10
  182. package/skills_ref/differential-review/README.md +0 -109
  183. package/skills_ref/differential-review/commands/diff-review.md +0 -21
  184. package/skills_ref/differential-review/skills/differential-review/SKILL.md +0 -220
  185. package/skills_ref/differential-review/skills/differential-review/adversarial.md +0 -203
  186. package/skills_ref/differential-review/skills/differential-review/methodology.md +0 -234
  187. package/skills_ref/differential-review/skills/differential-review/patterns.md +0 -300
  188. package/skills_ref/differential-review/skills/differential-review/reporting.md +0 -369
  189. package/skills_ref/dispatching-parallel-agents/SKILL.md +0 -180
  190. package/skills_ref/doc-coauthoring/SKILL.md +0 -375
  191. package/skills_ref/docx/LICENSE.txt +0 -30
  192. package/skills_ref/docx/SKILL.md +0 -481
  193. package/skills_ref/docx/scripts/__init__.py +0 -1
  194. package/skills_ref/docx/scripts/accept_changes.py +0 -135
  195. package/skills_ref/docx/scripts/comment.py +0 -318
  196. package/skills_ref/docx/scripts/office/helpers/__init__.py +0 -0
  197. package/skills_ref/docx/scripts/office/helpers/merge_runs.py +0 -199
  198. package/skills_ref/docx/scripts/office/helpers/simplify_redlines.py +0 -197
  199. package/skills_ref/docx/scripts/office/pack.py +0 -159
  200. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  201. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  202. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  203. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  204. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  205. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  206. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  207. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  208. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  209. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  210. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  211. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  212. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  213. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  214. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  215. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  216. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  217. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  218. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  219. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  220. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  221. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  222. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  223. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  224. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  225. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  226. package/skills_ref/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  227. package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  228. package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  229. package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  230. package/skills_ref/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  231. package/skills_ref/docx/scripts/office/schemas/mce/mc.xsd +0 -75
  232. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  233. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  234. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  235. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  236. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  237. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  238. package/skills_ref/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  239. package/skills_ref/docx/scripts/office/soffice.py +0 -183
  240. package/skills_ref/docx/scripts/office/unpack.py +0 -132
  241. package/skills_ref/docx/scripts/office/validate.py +0 -111
  242. package/skills_ref/docx/scripts/office/validators/__init__.py +0 -15
  243. package/skills_ref/docx/scripts/office/validators/base.py +0 -847
  244. package/skills_ref/docx/scripts/office/validators/docx.py +0 -446
  245. package/skills_ref/docx/scripts/office/validators/pptx.py +0 -275
  246. package/skills_ref/docx/scripts/office/validators/redlining.py +0 -247
  247. package/skills_ref/docx/scripts/templates/comments.xml +0 -3
  248. package/skills_ref/docx/scripts/templates/commentsExtended.xml +0 -3
  249. package/skills_ref/docx/scripts/templates/commentsExtensible.xml +0 -3
  250. package/skills_ref/docx/scripts/templates/commentsIds.xml +0 -3
  251. package/skills_ref/docx/scripts/templates/people.xml +0 -3
  252. package/skills_ref/durable-objects/SKILL.md +0 -186
  253. package/skills_ref/durable-objects/references/rules.md +0 -286
  254. package/skills_ref/durable-objects/references/testing.md +0 -264
  255. package/skills_ref/durable-objects/references/workers.md +0 -346
  256. package/skills_ref/email-draft-polish/SKILL.md +0 -24
  257. package/skills_ref/error-message-explainer/SKILL.md +0 -27
  258. package/skills_ref/fal-image-edit/SKILL.md +0 -249
  259. package/skills_ref/fal-image-edit/scripts/edit-image.sh +0 -199
  260. package/skills_ref/figma-implement-design/SKILL.md +0 -264
  261. package/skills_ref/git-worktrees/SKILL.md +0 -218
  262. package/skills_ref/github/SKILL.md +0 -210
  263. package/skills_ref/gog/SKILL.md +0 -116
  264. package/skills_ref/goplaces/SKILL.md +0 -52
  265. package/skills_ref/himalaya/SKILL.md +0 -257
  266. package/skills_ref/hugging-face-cli/SKILL.md +0 -186
  267. package/skills_ref/hugging-face-cli/references/commands.md +0 -954
  268. package/skills_ref/hugging-face-cli/references/examples.md +0 -374
  269. package/skills_ref/hugging-face-evaluation/SKILL.md +0 -651
  270. package/skills_ref/hugging-face-evaluation/examples/.env.example +0 -7
  271. package/skills_ref/hugging-face-evaluation/examples/USAGE_EXAMPLES.md +0 -382
  272. package/skills_ref/hugging-face-evaluation/examples/artificial_analysis_to_hub.py +0 -141
  273. package/skills_ref/hugging-face-evaluation/examples/example_readme_tables.md +0 -135
  274. package/skills_ref/hugging-face-evaluation/examples/metric_mapping.json +0 -50
  275. package/skills_ref/hugging-face-evaluation/requirements.txt +0 -20
  276. package/skills_ref/hugging-face-evaluation/scripts/evaluation_manager.py +0 -1374
  277. package/skills_ref/hugging-face-evaluation/scripts/inspect_eval_uv.py +0 -104
  278. package/skills_ref/hugging-face-evaluation/scripts/inspect_vllm_uv.py +0 -317
  279. package/skills_ref/hugging-face-evaluation/scripts/lighteval_vllm_uv.py +0 -303
  280. package/skills_ref/hugging-face-evaluation/scripts/run_eval_job.py +0 -98
  281. package/skills_ref/hugging-face-evaluation/scripts/run_vllm_eval_job.py +0 -331
  282. package/skills_ref/hugging-face-evaluation/scripts/test_extraction.py +0 -206
  283. package/skills_ref/hugging-face-model-trainer/SKILL.md +0 -718
  284. package/skills_ref/hugging-face-model-trainer/references/gguf_conversion.md +0 -296
  285. package/skills_ref/hugging-face-model-trainer/references/hardware_guide.md +0 -283
  286. package/skills_ref/hugging-face-model-trainer/references/hub_saving.md +0 -364
  287. package/skills_ref/hugging-face-model-trainer/references/reliability_principles.md +0 -371
  288. package/skills_ref/hugging-face-model-trainer/references/trackio_guide.md +0 -189
  289. package/skills_ref/hugging-face-model-trainer/references/training_methods.md +0 -150
  290. package/skills_ref/hugging-face-model-trainer/references/training_patterns.md +0 -203
  291. package/skills_ref/hugging-face-model-trainer/references/troubleshooting.md +0 -282
  292. package/skills_ref/hugging-face-model-trainer/references/unsloth.md +0 -313
  293. package/skills_ref/hugging-face-model-trainer/scripts/convert_to_gguf.py +0 -424
  294. package/skills_ref/hugging-face-model-trainer/scripts/dataset_inspector.py +0 -417
  295. package/skills_ref/hugging-face-model-trainer/scripts/estimate_cost.py +0 -150
  296. package/skills_ref/hugging-face-model-trainer/scripts/train_dpo_example.py +0 -106
  297. package/skills_ref/hugging-face-model-trainer/scripts/train_grpo_example.py +0 -89
  298. package/skills_ref/hugging-face-model-trainer/scripts/train_sft_example.py +0 -122
  299. package/skills_ref/hugging-face-model-trainer/scripts/unsloth_sft_example.py +0 -512
  300. package/skills_ref/imagegen/SKILL.md +0 -174
  301. package/skills_ref/insecure-defaults/.claude-plugin/plugin.json +0 -10
  302. package/skills_ref/insecure-defaults/README.md +0 -45
  303. package/skills_ref/insecure-defaults/skills/insecure-defaults/SKILL.md +0 -117
  304. package/skills_ref/insecure-defaults/skills/insecure-defaults/references/examples.md +0 -409
  305. package/skills_ref/jupyter-notebook/SKILL.md +0 -107
  306. package/skills_ref/linear/SKILL.md +0 -87
  307. package/skills_ref/linter-fix-guide/SKILL.md +0 -27
  308. package/skills_ref/log-summarizer/SKILL.md +0 -27
  309. package/skills_ref/mcp-builder/LICENSE.txt +0 -202
  310. package/skills_ref/mcp-builder/SKILL.md +0 -236
  311. package/skills_ref/mcp-builder/reference/evaluation.md +0 -602
  312. package/skills_ref/mcp-builder/reference/mcp_best_practices.md +0 -249
  313. package/skills_ref/mcp-builder/reference/node_mcp_server.md +0 -970
  314. package/skills_ref/mcp-builder/reference/python_mcp_server.md +0 -719
  315. package/skills_ref/mcp-builder/scripts/connections.py +0 -151
  316. package/skills_ref/mcp-builder/scripts/evaluation.py +0 -373
  317. package/skills_ref/mcp-builder/scripts/example_evaluation.xml +0 -22
  318. package/skills_ref/mcp-builder/scripts/requirements.txt +0 -2
  319. package/skills_ref/memory/SKILL.md +0 -129
  320. package/skills_ref/modern-python/.claude-plugin/plugin.json +0 -10
  321. package/skills_ref/modern-python/README.md +0 -66
  322. package/skills_ref/modern-python/hooks/hooks.json +0 -16
  323. package/skills_ref/modern-python/hooks/setup-shims.bats +0 -70
  324. package/skills_ref/modern-python/hooks/setup-shims.sh +0 -24
  325. package/skills_ref/modern-python/hooks/shims/pip +0 -27
  326. package/skills_ref/modern-python/hooks/shims/pip-shim.bats +0 -45
  327. package/skills_ref/modern-python/hooks/shims/pip3 +0 -27
  328. package/skills_ref/modern-python/hooks/shims/pipx +0 -41
  329. package/skills_ref/modern-python/hooks/shims/pipx-shim.bats +0 -64
  330. package/skills_ref/modern-python/hooks/shims/python +0 -26
  331. package/skills_ref/modern-python/hooks/shims/python-shim.bats +0 -53
  332. package/skills_ref/modern-python/hooks/shims/python3 +0 -26
  333. package/skills_ref/modern-python/hooks/shims/uv +0 -27
  334. package/skills_ref/modern-python/hooks/shims/uv-shim.bats +0 -47
  335. package/skills_ref/modern-python/skills/modern-python/SKILL.md +0 -333
  336. package/skills_ref/modern-python/skills/modern-python/references/dependabot.md +0 -43
  337. package/skills_ref/modern-python/skills/modern-python/references/migration-checklist.md +0 -141
  338. package/skills_ref/modern-python/skills/modern-python/references/pep723-scripts.md +0 -259
  339. package/skills_ref/modern-python/skills/modern-python/references/prek.md +0 -211
  340. package/skills_ref/modern-python/skills/modern-python/references/pyproject.md +0 -254
  341. package/skills_ref/modern-python/skills/modern-python/references/ruff-config.md +0 -240
  342. package/skills_ref/modern-python/skills/modern-python/references/security-setup.md +0 -255
  343. package/skills_ref/modern-python/skills/modern-python/references/testing.md +0 -284
  344. package/skills_ref/modern-python/skills/modern-python/references/uv-commands.md +0 -200
  345. package/skills_ref/modern-python/skills/modern-python/templates/dependabot.yml +0 -36
  346. package/skills_ref/modern-python/skills/modern-python/templates/pre-commit-config.yaml +0 -66
  347. package/skills_ref/nano-banana-pro/SKILL.md +0 -58
  348. package/skills_ref/netlify-deploy/SKILL.md +0 -233
  349. package/skills_ref/notion/SKILL.md +0 -304
  350. package/skills_ref/notion-knowledge-capture/SKILL.md +0 -56
  351. package/skills_ref/notion-meeting-intelligence/SKILL.md +0 -60
  352. package/skills_ref/notion-research-documentation/SKILL.md +0 -59
  353. package/skills_ref/notion-spec-to-implementation/SKILL.md +0 -58
  354. package/skills_ref/obsidian/SKILL.md +0 -81
  355. package/skills_ref/openai-docs/SKILL.md +0 -56
  356. package/skills_ref/openhue/SKILL.md +0 -112
  357. package/skills_ref/pdf/SKILL.md +0 -69
  358. package/skills_ref/postgres/README.md +0 -77
  359. package/skills_ref/postgres/SKILL.md +0 -129
  360. package/skills_ref/postgres/connections.example.json +0 -34
  361. package/skills_ref/postgres/requirements.txt +0 -1
  362. package/skills_ref/postgres/scripts/query.py +0 -262
  363. package/skills_ref/pptx/LICENSE.txt +0 -30
  364. package/skills_ref/pptx/SKILL.md +0 -232
  365. package/skills_ref/pptx/editing.md +0 -205
  366. package/skills_ref/pptx/pptxgenjs.md +0 -420
  367. package/skills_ref/pptx/scripts/__init__.py +0 -0
  368. package/skills_ref/pptx/scripts/add_slide.py +0 -195
  369. package/skills_ref/pptx/scripts/clean.py +0 -286
  370. package/skills_ref/pptx/scripts/office/helpers/__init__.py +0 -0
  371. package/skills_ref/pptx/scripts/office/helpers/merge_runs.py +0 -199
  372. package/skills_ref/pptx/scripts/office/helpers/simplify_redlines.py +0 -197
  373. package/skills_ref/pptx/scripts/office/pack.py +0 -159
  374. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  375. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  376. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  377. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  378. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  379. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  380. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  381. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  382. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  383. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  384. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  385. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  386. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  387. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  388. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  389. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  390. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  391. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  392. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  393. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  394. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  395. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  396. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  397. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  398. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  399. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  400. package/skills_ref/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  401. package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  402. package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  403. package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  404. package/skills_ref/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  405. package/skills_ref/pptx/scripts/office/schemas/mce/mc.xsd +0 -75
  406. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  407. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  408. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  409. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  410. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  411. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  412. package/skills_ref/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  413. package/skills_ref/pptx/scripts/office/soffice.py +0 -183
  414. package/skills_ref/pptx/scripts/office/unpack.py +0 -132
  415. package/skills_ref/pptx/scripts/office/validate.py +0 -111
  416. package/skills_ref/pptx/scripts/office/validators/__init__.py +0 -15
  417. package/skills_ref/pptx/scripts/office/validators/base.py +0 -847
  418. package/skills_ref/pptx/scripts/office/validators/docx.py +0 -446
  419. package/skills_ref/pptx/scripts/office/validators/pptx.py +0 -275
  420. package/skills_ref/pptx/scripts/office/validators/redlining.py +0 -247
  421. package/skills_ref/pptx/scripts/thumbnail.py +0 -289
  422. package/skills_ref/property-based-testing/.claude-plugin/plugin.json +0 -9
  423. package/skills_ref/property-based-testing/README.md +0 -47
  424. package/skills_ref/property-based-testing/skills/property-based-testing/README.md +0 -88
  425. package/skills_ref/property-based-testing/skills/property-based-testing/SKILL.md +0 -123
  426. package/skills_ref/property-based-testing/skills/property-based-testing/references/design.md +0 -191
  427. package/skills_ref/property-based-testing/skills/property-based-testing/references/generating.md +0 -204
  428. package/skills_ref/property-based-testing/skills/property-based-testing/references/interpreting-failures.md +0 -239
  429. package/skills_ref/property-based-testing/skills/property-based-testing/references/libraries.md +0 -130
  430. package/skills_ref/property-based-testing/skills/property-based-testing/references/refactoring.md +0 -181
  431. package/skills_ref/property-based-testing/skills/property-based-testing/references/reviewing.md +0 -209
  432. package/skills_ref/property-based-testing/skills/property-based-testing/references/strategies.md +0 -124
  433. package/skills_ref/react-best-practices/AGENTS.md +0 -2934
  434. package/skills_ref/react-best-practices/README.md +0 -123
  435. package/skills_ref/react-best-practices/SKILL.md +0 -136
  436. package/skills_ref/react-best-practices/metadata.json +0 -15
  437. package/skills_ref/react-best-practices/rules/_sections.md +0 -46
  438. package/skills_ref/react-best-practices/rules/_template.md +0 -28
  439. package/skills_ref/react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  440. package/skills_ref/react-best-practices/rules/advanced-init-once.md +0 -42
  441. package/skills_ref/react-best-practices/rules/advanced-use-latest.md +0 -39
  442. package/skills_ref/react-best-practices/rules/async-api-routes.md +0 -38
  443. package/skills_ref/react-best-practices/rules/async-defer-await.md +0 -80
  444. package/skills_ref/react-best-practices/rules/async-dependencies.md +0 -51
  445. package/skills_ref/react-best-practices/rules/async-parallel.md +0 -28
  446. package/skills_ref/react-best-practices/rules/async-suspense-boundaries.md +0 -99
  447. package/skills_ref/react-best-practices/rules/bundle-barrel-imports.md +0 -59
  448. package/skills_ref/react-best-practices/rules/bundle-conditional.md +0 -31
  449. package/skills_ref/react-best-practices/rules/bundle-defer-third-party.md +0 -49
  450. package/skills_ref/react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  451. package/skills_ref/react-best-practices/rules/bundle-preload.md +0 -50
  452. package/skills_ref/react-best-practices/rules/client-event-listeners.md +0 -74
  453. package/skills_ref/react-best-practices/rules/client-localstorage-schema.md +0 -71
  454. package/skills_ref/react-best-practices/rules/client-passive-event-listeners.md +0 -48
  455. package/skills_ref/react-best-practices/rules/client-swr-dedup.md +0 -56
  456. package/skills_ref/react-best-practices/rules/js-batch-dom-css.md +0 -107
  457. package/skills_ref/react-best-practices/rules/js-cache-function-results.md +0 -80
  458. package/skills_ref/react-best-practices/rules/js-cache-property-access.md +0 -28
  459. package/skills_ref/react-best-practices/rules/js-cache-storage.md +0 -70
  460. package/skills_ref/react-best-practices/rules/js-combine-iterations.md +0 -32
  461. package/skills_ref/react-best-practices/rules/js-early-exit.md +0 -50
  462. package/skills_ref/react-best-practices/rules/js-hoist-regexp.md +0 -45
  463. package/skills_ref/react-best-practices/rules/js-index-maps.md +0 -37
  464. package/skills_ref/react-best-practices/rules/js-length-check-first.md +0 -49
  465. package/skills_ref/react-best-practices/rules/js-min-max-loop.md +0 -82
  466. package/skills_ref/react-best-practices/rules/js-set-map-lookups.md +0 -24
  467. package/skills_ref/react-best-practices/rules/js-tosorted-immutable.md +0 -57
  468. package/skills_ref/react-best-practices/rules/rendering-activity.md +0 -26
  469. package/skills_ref/react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  470. package/skills_ref/react-best-practices/rules/rendering-conditional-render.md +0 -40
  471. package/skills_ref/react-best-practices/rules/rendering-content-visibility.md +0 -38
  472. package/skills_ref/react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  473. package/skills_ref/react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  474. package/skills_ref/react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  475. package/skills_ref/react-best-practices/rules/rendering-svg-precision.md +0 -28
  476. package/skills_ref/react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  477. package/skills_ref/react-best-practices/rules/rerender-defer-reads.md +0 -39
  478. package/skills_ref/react-best-practices/rules/rerender-dependencies.md +0 -45
  479. package/skills_ref/react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  480. package/skills_ref/react-best-practices/rules/rerender-derived-state.md +0 -29
  481. package/skills_ref/react-best-practices/rules/rerender-functional-setstate.md +0 -74
  482. package/skills_ref/react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  483. package/skills_ref/react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  484. package/skills_ref/react-best-practices/rules/rerender-memo.md +0 -44
  485. package/skills_ref/react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  486. package/skills_ref/react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  487. package/skills_ref/react-best-practices/rules/rerender-transitions.md +0 -40
  488. package/skills_ref/react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  489. package/skills_ref/react-best-practices/rules/server-after-nonblocking.md +0 -73
  490. package/skills_ref/react-best-practices/rules/server-auth-actions.md +0 -96
  491. package/skills_ref/react-best-practices/rules/server-cache-lru.md +0 -41
  492. package/skills_ref/react-best-practices/rules/server-cache-react.md +0 -76
  493. package/skills_ref/react-best-practices/rules/server-dedup-props.md +0 -65
  494. package/skills_ref/react-best-practices/rules/server-parallel-fetching.md +0 -83
  495. package/skills_ref/react-best-practices/rules/server-serialization.md +0 -38
  496. package/skills_ref/receiving-code-review/SKILL.md +0 -213
  497. package/skills_ref/registry.json +0 -1493
  498. package/skills_ref/render-deploy/SKILL.md +0 -462
  499. package/skills_ref/requesting-code-review/SKILL.md +0 -105
  500. package/skills_ref/requesting-code-review/code-reviewer.md +0 -146
  501. package/skills_ref/screen-capture/SKILL.md +0 -162
  502. package/skills_ref/security-best-practices/LICENSE.txt +0 -201
  503. package/skills_ref/security-best-practices/SKILL.md +0 -86
  504. package/skills_ref/security-best-practices/agents/openai.yaml +0 -4
  505. package/skills_ref/security-best-practices/references/golang-general-backend-security.md +0 -826
  506. package/skills_ref/security-best-practices/references/javascript-express-web-server-security.md +0 -1158
  507. package/skills_ref/security-best-practices/references/javascript-general-web-frontend-security.md +0 -747
  508. package/skills_ref/security-best-practices/references/javascript-jquery-web-frontend-security.md +0 -678
  509. package/skills_ref/security-best-practices/references/javascript-typescript-nextjs-web-server-security.md +0 -1144
  510. package/skills_ref/security-best-practices/references/javascript-typescript-react-web-frontend-security.md +0 -990
  511. package/skills_ref/security-best-practices/references/javascript-typescript-vue-web-frontend-security.md +0 -791
  512. package/skills_ref/security-best-practices/references/python-django-web-server-security.md +0 -882
  513. package/skills_ref/security-best-practices/references/python-fastapi-web-server-security.md +0 -1036
  514. package/skills_ref/security-best-practices/references/python-flask-web-server-security.md +0 -705
  515. package/skills_ref/security-ownership-map/LICENSE.txt +0 -201
  516. package/skills_ref/security-ownership-map/SKILL.md +0 -206
  517. package/skills_ref/security-ownership-map/agents/openai.yaml +0 -4
  518. package/skills_ref/security-ownership-map/references/neo4j-import.md +0 -60
  519. package/skills_ref/security-ownership-map/scripts/build_ownership_map.py +0 -956
  520. package/skills_ref/security-ownership-map/scripts/community_maintainers.py +0 -544
  521. package/skills_ref/security-ownership-map/scripts/query_ownership.py +0 -483
  522. package/skills_ref/security-ownership-map/scripts/run_ownership_map.py +0 -200
  523. package/skills_ref/security-threat-model/LICENSE.txt +0 -201
  524. package/skills_ref/security-threat-model/SKILL.md +0 -81
  525. package/skills_ref/security-threat-model/agents/openai.yaml +0 -4
  526. package/skills_ref/security-threat-model/references/prompt-template.md +0 -255
  527. package/skills_ref/security-threat-model/references/security-controls-and-assets.md +0 -32
  528. package/skills_ref/sentry/SKILL.md +0 -123
  529. package/skills_ref/skill-creator/SKILL.md +0 -372
  530. package/skills_ref/sora/SKILL.md +0 -153
  531. package/skills_ref/speech/SKILL.md +0 -144
  532. package/skills_ref/spotify-player/SKILL.md +0 -64
  533. package/skills_ref/static-analysis/.claude-plugin/plugin.json +0 -8
  534. package/skills_ref/static-analysis/README.md +0 -65
  535. package/skills_ref/static-analysis/agents/semgrep-scanner.md +0 -71
  536. package/skills_ref/static-analysis/agents/semgrep-triager.md +0 -107
  537. package/skills_ref/static-analysis/skills/codeql/SKILL.md +0 -119
  538. package/skills_ref/static-analysis/skills/codeql/references/diagnostic-query-templates.md +0 -339
  539. package/skills_ref/static-analysis/skills/codeql/references/language-details.md +0 -207
  540. package/skills_ref/static-analysis/skills/codeql/references/performance-tuning.md +0 -111
  541. package/skills_ref/static-analysis/skills/codeql/references/ruleset-catalog.md +0 -63
  542. package/skills_ref/static-analysis/skills/codeql/references/threat-models.md +0 -44
  543. package/skills_ref/static-analysis/skills/codeql/workflows/build-database.md +0 -669
  544. package/skills_ref/static-analysis/skills/codeql/workflows/create-data-extensions.md +0 -536
  545. package/skills_ref/static-analysis/skills/codeql/workflows/run-analysis.md +0 -436
  546. package/skills_ref/static-analysis/skills/sarif-parsing/SKILL.md +0 -479
  547. package/skills_ref/static-analysis/skills/sarif-parsing/resources/jq-queries.md +0 -162
  548. package/skills_ref/static-analysis/skills/sarif-parsing/resources/sarif_helpers.py +0 -331
  549. package/skills_ref/static-analysis/skills/semgrep/SKILL.md +0 -431
  550. package/skills_ref/static-analysis/skills/semgrep/references/rulesets.md +0 -162
  551. package/skills_ref/static-analysis/skills/semgrep/references/scanner-task-prompt.md +0 -102
  552. package/skills_ref/static-analysis/skills/semgrep/references/triage-task-prompt.md +0 -122
  553. package/skills_ref/static-analysis/skills/semgrep/scripts/merge_triaged_sarif.py +0 -252
  554. package/skills_ref/summarize/SKILL.md +0 -87
  555. package/skills_ref/tdd/SKILL.md +0 -371
  556. package/skills_ref/tdd/testing-anti-patterns.md +0 -299
  557. package/skills_ref/telegram-send/SKILL.md +0 -99
  558. package/skills_ref/terraform/README.md +0 -105
  559. package/skills_ref/terraform/code-generation/.claude-plugin/plugin.json +0 -30
  560. package/skills_ref/terraform/code-generation/skills/azure-verified-modules/SKILL.md +0 -613
  561. package/skills_ref/terraform/code-generation/skills/terraform-style-guide/SKILL.md +0 -353
  562. package/skills_ref/terraform/code-generation/skills/terraform-test/SKILL.md +0 -1669
  563. package/skills_ref/terraform/module-generation/.claude-plugin/plugin.json +0 -30
  564. package/skills_ref/terraform/module-generation/skills/refactor-module/SKILL.md +0 -538
  565. package/skills_ref/terraform/module-generation/skills/terraform-stacks/SKILL.md +0 -468
  566. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/api-monitoring.md +0 -543
  567. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/component-blocks.md +0 -476
  568. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/deployment-blocks.md +0 -391
  569. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/examples.md +0 -1529
  570. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/linked-stacks.md +0 -187
  571. package/skills_ref/terraform/module-generation/skills/terraform-stacks/references/troubleshooting.md +0 -671
  572. package/skills_ref/terraform/provider-development/.claude-plugin/plugin.json +0 -13
  573. package/skills_ref/terraform/provider-development/skills/new-terraform-provider/SKILL.md +0 -25
  574. package/skills_ref/terraform/provider-development/skills/new-terraform-provider/assets/main.go +0 -40
  575. package/skills_ref/terraform/provider-development/skills/provider-actions/SKILL.md +0 -478
  576. package/skills_ref/terraform/provider-development/skills/provider-resources/SKILL.md +0 -599
  577. package/skills_ref/terraform/provider-development/skills/run-acceptance-tests/SKILL.md +0 -41
  578. package/skills_ref/theme-factory/LICENSE.txt +0 -202
  579. package/skills_ref/theme-factory/SKILL.md +0 -59
  580. package/skills_ref/theme-factory/theme-showcase.pdf +0 -0
  581. package/skills_ref/theme-factory/themes/arctic-frost.md +0 -19
  582. package/skills_ref/theme-factory/themes/botanical-garden.md +0 -19
  583. package/skills_ref/theme-factory/themes/desert-rose.md +0 -19
  584. package/skills_ref/theme-factory/themes/forest-canopy.md +0 -19
  585. package/skills_ref/theme-factory/themes/golden-hour.md +0 -19
  586. package/skills_ref/theme-factory/themes/midnight-galaxy.md +0 -19
  587. package/skills_ref/theme-factory/themes/modern-minimalist.md +0 -19
  588. package/skills_ref/theme-factory/themes/ocean-depths.md +0 -19
  589. package/skills_ref/theme-factory/themes/sunset-boulevard.md +0 -19
  590. package/skills_ref/theme-factory/themes/tech-innovation.md +0 -19
  591. package/skills_ref/things-mac/SKILL.md +0 -86
  592. package/skills_ref/tmux/SKILL.md +0 -153
  593. package/skills_ref/transcribe/SKILL.md +0 -81
  594. package/skills_ref/trello/SKILL.md +0 -95
  595. package/skills_ref/tts/SKILL.md +0 -99
  596. package/skills_ref/vercel-deploy/SKILL.md +0 -115
  597. package/skills_ref/video-downloader/SKILL.md +0 -99
  598. package/skills_ref/video-downloader/scripts/download_video.py +0 -145
  599. package/skills_ref/video-frames/SKILL.md +0 -46
  600. package/skills_ref/vision-click/SKILL.md +0 -128
  601. package/skills_ref/weather/SKILL.md +0 -112
  602. package/skills_ref/web-artifacts-builder/LICENSE.txt +0 -202
  603. package/skills_ref/web-artifacts-builder/SKILL.md +0 -74
  604. package/skills_ref/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  605. package/skills_ref/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  606. package/skills_ref/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  607. package/skills_ref/web-perf/SKILL.md +0 -193
  608. package/skills_ref/web-routing/SKILL.md +0 -26
  609. package/skills_ref/whatsapp/SKILL.md +0 -255
  610. package/skills_ref/whatsapp/assets/agent-app-integration-example.json +0 -35
  611. package/skills_ref/whatsapp/assets/databases-example.json +0 -11
  612. package/skills_ref/whatsapp/assets/function-decide-route-interactive-buttons.json +0 -6
  613. package/skills_ref/whatsapp/assets/functions-example.json +0 -5
  614. package/skills_ref/whatsapp/assets/workflow-agent-simple.json +0 -31
  615. package/skills_ref/whatsapp/assets/workflow-api-template-wait-agent.json +0 -59
  616. package/skills_ref/whatsapp/assets/workflow-customer-support-intake-agent.json +0 -56
  617. package/skills_ref/whatsapp/assets/workflow-decision.json +0 -83
  618. package/skills_ref/whatsapp/assets/workflow-interactive-buttons-decide-ai.json +0 -89
  619. package/skills_ref/whatsapp/assets/workflow-interactive-buttons-decide-function.json +0 -88
  620. package/skills_ref/whatsapp/assets/workflow-linear.json +0 -53
  621. package/skills_ref/whatsapp/package.json +0 -10
  622. package/skills_ref/whatsapp/references/app-integrations.md +0 -89
  623. package/skills_ref/whatsapp/references/databases-reference.md +0 -21
  624. package/skills_ref/whatsapp/references/execution-context.md +0 -42
  625. package/skills_ref/whatsapp/references/function-contracts.md +0 -55
  626. package/skills_ref/whatsapp/references/functions-payloads.md +0 -87
  627. package/skills_ref/whatsapp/references/functions-reference.md +0 -133
  628. package/skills_ref/whatsapp/references/graph-contract.md +0 -145
  629. package/skills_ref/whatsapp/references/node-types.md +0 -430
  630. package/skills_ref/whatsapp/references/triggers.md +0 -20
  631. package/skills_ref/whatsapp/references/workflow-overview.md +0 -22
  632. package/skills_ref/whatsapp/references/workflow-reference.md +0 -123
  633. package/skills_ref/whatsapp/scripts/configure-prop.js +0 -113
  634. package/skills_ref/whatsapp/scripts/create-connect-token.js +0 -38
  635. package/skills_ref/whatsapp/scripts/create-function.js +0 -64
  636. package/skills_ref/whatsapp/scripts/create-integration.js +0 -137
  637. package/skills_ref/whatsapp/scripts/create-row.js +0 -47
  638. package/skills_ref/whatsapp/scripts/create-trigger.js +0 -88
  639. package/skills_ref/whatsapp/scripts/create-workflow.js +0 -85
  640. package/skills_ref/whatsapp/scripts/delete-integration.js +0 -44
  641. package/skills_ref/whatsapp/scripts/delete-row.js +0 -49
  642. package/skills_ref/whatsapp/scripts/delete-trigger.js +0 -44
  643. package/skills_ref/whatsapp/scripts/deploy-function.js +0 -47
  644. package/skills_ref/whatsapp/scripts/edit-graph.js +0 -289
  645. package/skills_ref/whatsapp/scripts/get-action-schema.js +0 -44
  646. package/skills_ref/whatsapp/scripts/get-context-value.js +0 -80
  647. package/skills_ref/whatsapp/scripts/get-execution-event.js +0 -55
  648. package/skills_ref/whatsapp/scripts/get-execution.js +0 -44
  649. package/skills_ref/whatsapp/scripts/get-function.js +0 -43
  650. package/skills_ref/whatsapp/scripts/get-graph.js +0 -85
  651. package/skills_ref/whatsapp/scripts/get-table.js +0 -45
  652. package/skills_ref/whatsapp/scripts/get-workflow.js +0 -44
  653. package/skills_ref/whatsapp/scripts/invoke-function.js +0 -60
  654. package/skills_ref/whatsapp/scripts/lib/databases/args.js +0 -87
  655. package/skills_ref/whatsapp/scripts/lib/databases/filters.js +0 -30
  656. package/skills_ref/whatsapp/scripts/lib/databases/kapso-api.js +0 -70
  657. package/skills_ref/whatsapp/scripts/lib/functions/args.js +0 -55
  658. package/skills_ref/whatsapp/scripts/lib/functions/kapso-api.js +0 -70
  659. package/skills_ref/whatsapp/scripts/lib/workflows/args.js +0 -53
  660. package/skills_ref/whatsapp/scripts/lib/workflows/kapso-api.js +0 -123
  661. package/skills_ref/whatsapp/scripts/lib/workflows/result.js +0 -16
  662. package/skills_ref/whatsapp/scripts/list-accounts.js +0 -62
  663. package/skills_ref/whatsapp/scripts/list-apps.js +0 -42
  664. package/skills_ref/whatsapp/scripts/list-execution-events.js +0 -61
  665. package/skills_ref/whatsapp/scripts/list-executions.js +0 -53
  666. package/skills_ref/whatsapp/scripts/list-function-invocations.js +0 -53
  667. package/skills_ref/whatsapp/scripts/list-functions.js +0 -41
  668. package/skills_ref/whatsapp/scripts/list-integrations.js +0 -41
  669. package/skills_ref/whatsapp/scripts/list-provider-models.js +0 -48
  670. package/skills_ref/whatsapp/scripts/list-tables.js +0 -41
  671. package/skills_ref/whatsapp/scripts/list-triggers.js +0 -44
  672. package/skills_ref/whatsapp/scripts/list-whatsapp-phone-numbers.js +0 -56
  673. package/skills_ref/whatsapp/scripts/list-workflows.js +0 -44
  674. package/skills_ref/whatsapp/scripts/openapi-explore.mjs +0 -1273
  675. package/skills_ref/whatsapp/scripts/query-rows.js +0 -71
  676. package/skills_ref/whatsapp/scripts/reload-props.js +0 -110
  677. package/skills_ref/whatsapp/scripts/resume-execution.js +0 -75
  678. package/skills_ref/whatsapp/scripts/search-actions.js +0 -64
  679. package/skills_ref/whatsapp/scripts/update-execution-status.js +0 -51
  680. package/skills_ref/whatsapp/scripts/update-function.js +0 -65
  681. package/skills_ref/whatsapp/scripts/update-graph.js +0 -154
  682. package/skills_ref/whatsapp/scripts/update-integration.js +0 -82
  683. package/skills_ref/whatsapp/scripts/update-row.js +0 -51
  684. package/skills_ref/whatsapp/scripts/update-trigger.js +0 -60
  685. package/skills_ref/whatsapp/scripts/update-workflow-settings.js +0 -67
  686. package/skills_ref/whatsapp/scripts/upsert-row.js +0 -64
  687. package/skills_ref/whatsapp/scripts/validate-graph.js +0 -293
  688. package/skills_ref/whatsapp/scripts/variables-delete.js +0 -37
  689. package/skills_ref/whatsapp/scripts/variables-list.js +0 -55
  690. package/skills_ref/whatsapp/scripts/variables-set.js +0 -39
  691. package/skills_ref/writing-plans/SKILL.md +0 -116
  692. package/skills_ref/xlsx/LICENSE.txt +0 -30
  693. package/skills_ref/xlsx/SKILL.md +0 -292
  694. package/skills_ref/xlsx/scripts/office/helpers/__init__.py +0 -0
  695. package/skills_ref/xlsx/scripts/office/helpers/merge_runs.py +0 -199
  696. package/skills_ref/xlsx/scripts/office/helpers/simplify_redlines.py +0 -197
  697. package/skills_ref/xlsx/scripts/office/pack.py +0 -159
  698. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  699. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  700. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  701. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  702. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  703. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  704. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  705. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  706. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  707. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  708. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  709. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  710. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  711. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  712. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  713. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  714. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  715. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  716. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  717. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  718. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  719. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  720. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  721. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  722. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  723. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  724. package/skills_ref/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  725. package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  726. package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  727. package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  728. package/skills_ref/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  729. package/skills_ref/xlsx/scripts/office/schemas/mce/mc.xsd +0 -75
  730. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +0 -560
  731. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +0 -67
  732. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +0 -14
  733. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -20
  734. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -13
  735. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  736. package/skills_ref/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -8
  737. package/skills_ref/xlsx/scripts/office/soffice.py +0 -183
  738. package/skills_ref/xlsx/scripts/office/unpack.py +0 -132
  739. package/skills_ref/xlsx/scripts/office/validate.py +0 -111
  740. package/skills_ref/xlsx/scripts/office/validators/__init__.py +0 -15
  741. package/skills_ref/xlsx/scripts/office/validators/base.py +0 -847
  742. package/skills_ref/xlsx/scripts/office/validators/docx.py +0 -446
  743. package/skills_ref/xlsx/scripts/office/validators/pptx.py +0 -275
  744. package/skills_ref/xlsx/scripts/office/validators/redlining.py +0 -247
  745. package/skills_ref/xlsx/scripts/recalc.py +0 -184
  746. package/skills_ref/xurl/SKILL.md +0 -461
@@ -1,956 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Build a security ownership map from git history."""
3
-
4
- from __future__ import annotations
5
-
6
- import argparse
7
- import csv
8
- import datetime as dt
9
- import fnmatch
10
- import json
11
- import math
12
- import os
13
- import re
14
- import subprocess
15
- import sys
16
- from collections import defaultdict
17
- from pathlib import Path
18
- from typing import Iterable
19
-
20
- DEFAULT_SENSITIVE_RULES: list[tuple[str, str, float]] = [
21
- ("**/auth/**", "auth", 1.0),
22
- ("**/oauth/**", "auth", 1.0),
23
- ("**/rbac/**", "auth", 1.0),
24
- ("**/session/**", "auth", 1.0),
25
- ("**/token/**", "auth", 1.0),
26
- ("**/crypto/**", "crypto", 1.0),
27
- ("**/tls/**", "crypto", 1.0),
28
- ("**/ssl/**", "crypto", 1.0),
29
- ("**/secrets/**", "secrets", 1.0),
30
- ("**/keys/**", "secrets", 1.0),
31
- ("**/*.pem", "secrets", 1.0),
32
- ("**/*.key", "secrets", 1.0),
33
- ("**/*.p12", "secrets", 1.0),
34
- ("**/*.pfx", "secrets", 1.0),
35
- ("**/iam/**", "auth", 1.0),
36
- ("**/sso/**", "auth", 1.0),
37
- ]
38
-
39
- DEFAULT_AUTHOR_EXCLUDE_REGEXES = [
40
- "dependabot",
41
- ]
42
-
43
- DEFAULT_COCHANGE_EXCLUDES = [
44
- "**/Cargo.lock",
45
- "**/Cargo.toml",
46
- "**/package-lock.json",
47
- "**/yarn.lock",
48
- "**/pnpm-lock.yaml",
49
- "**/go.sum",
50
- "**/go.mod",
51
- "**/Gemfile.lock",
52
- "**/Pipfile.lock",
53
- "**/poetry.lock",
54
- "**/composer.lock",
55
- "**/.github/**",
56
- "**/.gitignore",
57
- "**/.gitattributes",
58
- "**/.gitmodules",
59
- "**/.editorconfig",
60
- "**/.vscode/**",
61
- "**/.idea/**",
62
- ]
63
-
64
-
65
- def parse_args() -> argparse.Namespace:
66
- parser = argparse.ArgumentParser(
67
- description="Build ownership graphs and security ownership summaries from git history."
68
- )
69
- parser.add_argument("--repo", default=".", help="Path to the git repo (default: .)")
70
- parser.add_argument(
71
- "--out",
72
- default="ownership-map-out",
73
- help="Output directory for graph artifacts",
74
- )
75
- parser.add_argument("--since", default=None, help="Limit git log to commits since date")
76
- parser.add_argument("--until", default=None, help="Limit git log to commits until date")
77
- parser.add_argument(
78
- "--identity",
79
- choices=("author", "committer"),
80
- default="author",
81
- help="Identity to attribute touches to",
82
- )
83
- parser.add_argument(
84
- "--date-field",
85
- choices=("author", "committer"),
86
- default="author",
87
- help="Date field to use for recency and bucketing",
88
- )
89
- parser.add_argument(
90
- "--include-merges",
91
- action="store_true",
92
- help="Include merge commits (excluded by default)",
93
- )
94
- parser.add_argument(
95
- "--half-life-days",
96
- type=float,
97
- default=180.0,
98
- help="Half life for recency weighting",
99
- )
100
- parser.add_argument(
101
- "--sensitive-config",
102
- default=None,
103
- help="CSV file with pattern,tag,weight for sensitive paths",
104
- )
105
- parser.add_argument(
106
- "--owner-threshold",
107
- type=float,
108
- default=0.5,
109
- help="Share threshold for hidden owner detection",
110
- )
111
- parser.add_argument(
112
- "--bus-factor-threshold",
113
- type=int,
114
- default=1,
115
- help="Bus factor threshold for hotspots",
116
- )
117
- parser.add_argument(
118
- "--stale-days",
119
- type=int,
120
- default=365,
121
- help="Days since last touch to consider stale",
122
- )
123
- parser.add_argument(
124
- "--min-touches",
125
- type=int,
126
- default=1,
127
- help="Minimum touches to keep an edge",
128
- )
129
- parser.add_argument(
130
- "--emit-commits",
131
- action="store_true",
132
- help="Write commit list to commits.jsonl",
133
- )
134
- parser.add_argument(
135
- "--author-exclude-regex",
136
- action="append",
137
- default=[],
138
- help="Regex for author name/email to exclude (repeatable)",
139
- )
140
- parser.add_argument(
141
- "--no-default-author-excludes",
142
- action="store_true",
143
- help="Disable default author excludes (dependabot)",
144
- )
145
- parser.add_argument(
146
- "--no-cochange",
147
- action="store_true",
148
- help="Disable co-change graph output",
149
- )
150
- parser.add_argument(
151
- "--cochange-max-files",
152
- type=int,
153
- default=50,
154
- help="Ignore commits touching more than this many files for co-change graph",
155
- )
156
- parser.add_argument(
157
- "--cochange-min-count",
158
- type=int,
159
- default=2,
160
- help="Minimum co-change count to keep file-file edge",
161
- )
162
- parser.add_argument(
163
- "--cochange-min-jaccard",
164
- type=float,
165
- default=0.05,
166
- help="Minimum Jaccard similarity to keep file-file edge",
167
- )
168
- parser.add_argument(
169
- "--cochange-exclude",
170
- action="append",
171
- default=[],
172
- help="Glob to exclude from co-change graph (repeatable)",
173
- )
174
- parser.add_argument(
175
- "--no-default-cochange-excludes",
176
- action="store_true",
177
- help="Disable default co-change excludes (lockfiles, .github, editor config)",
178
- )
179
- parser.add_argument(
180
- "--no-communities",
181
- dest="communities",
182
- action="store_false",
183
- help="Disable community detection (enabled by default, requires networkx)",
184
- )
185
- parser.add_argument(
186
- "--graphml",
187
- action="store_true",
188
- help="Emit ownership.graphml (requires networkx)",
189
- )
190
- parser.add_argument(
191
- "--max-community-files",
192
- type=int,
193
- default=50,
194
- help="Max files listed per community",
195
- )
196
- parser.add_argument(
197
- "--community-top-owners",
198
- type=int,
199
- default=5,
200
- help="Top maintainers saved per community",
201
- )
202
- parser.set_defaults(communities=True)
203
- return parser.parse_args()
204
-
205
-
206
- def load_sensitive_rules(path: str | None) -> list[tuple[str, str, float]]:
207
- if not path:
208
- return list(DEFAULT_SENSITIVE_RULES)
209
- rules: list[tuple[str, str, float]] = []
210
- with open(path, "r", encoding="utf-8") as handle:
211
- for raw in handle:
212
- line = raw.strip()
213
- if not line or line.startswith("#"):
214
- continue
215
- parts = [part.strip() for part in line.split(",")]
216
- if not parts:
217
- continue
218
- pattern = parts[0]
219
- tag = parts[1] if len(parts) > 1 and parts[1] else "sensitive"
220
- weight = float(parts[2]) if len(parts) > 2 and parts[2] else 1.0
221
- rules.append((pattern, tag, weight))
222
- return rules
223
-
224
-
225
- def parse_date(value: str) -> dt.datetime:
226
- parsed = dt.datetime.fromisoformat(value)
227
- if parsed.tzinfo is None:
228
- parsed = parsed.replace(tzinfo=dt.timezone.utc)
229
- return parsed
230
-
231
-
232
- def offset_minutes(timestamp: dt.datetime) -> int | None:
233
- offset = timestamp.utcoffset()
234
- if offset is None:
235
- return None
236
- return int(offset.total_seconds() / 60)
237
-
238
-
239
- def format_offset(minutes: int) -> str:
240
- sign = "+" if minutes >= 0 else "-"
241
- minutes = abs(minutes)
242
- return f"{sign}{minutes // 60:02d}:{minutes % 60:02d}"
243
-
244
-
245
- def recency_weighted(now: dt.datetime, when: dt.datetime, half_life_days: float) -> float:
246
- if half_life_days <= 0:
247
- return 1.0
248
- age_days = max(0.0, (now - when).total_seconds() / 86400.0)
249
- return math.exp(-math.log(2) * age_days / half_life_days)
250
-
251
-
252
- def match_sensitive(path: str, rules: Iterable[tuple[str, str, float]]) -> dict[str, float]:
253
- tags: dict[str, float] = defaultdict(float)
254
- posix = path.replace("\\", "/")
255
- for pattern, tag, weight in rules:
256
- patterns = [pattern]
257
- if pattern.startswith("**/"):
258
- patterns.append(pattern[3:])
259
- for candidate in patterns:
260
- if fnmatch.fnmatchcase(posix, candidate):
261
- tags[tag] += weight
262
- break
263
- return tags
264
-
265
-
266
- def matches_glob(path: str, pattern: str) -> bool:
267
- posix = path.replace("\\", "/")
268
- patterns = [pattern]
269
- if pattern.startswith("**/"):
270
- patterns.append(pattern[3:])
271
- return any(fnmatch.fnmatchcase(posix, candidate) for candidate in patterns)
272
-
273
-
274
- def is_excluded(path: str, patterns: Iterable[str]) -> bool:
275
- return any(matches_glob(path, pattern) for pattern in patterns)
276
-
277
-
278
- def author_excluded(name: str, email: str, patterns: Iterable[re.Pattern[str]]) -> bool:
279
- if not patterns:
280
- return False
281
- haystack = f"{name} {email}".strip()
282
- return any(pattern.search(haystack) for pattern in patterns)
283
-
284
-
285
- def compute_community_owners(
286
- community_files: Iterable[str],
287
- people: dict[str, dict[str, object]],
288
- file_people_touches: dict[str, dict[str, int]],
289
- file_people_recency: dict[str, dict[str, float]],
290
- file_people_sensitive: dict[str, dict[str, float]],
291
- top_n: int,
292
- ) -> dict[str, object]:
293
- touches_by_person: dict[str, int] = defaultdict(int)
294
- recency_by_person: dict[str, float] = defaultdict(float)
295
- sensitive_by_person: dict[str, float] = defaultdict(float)
296
-
297
- for path in community_files:
298
- for person, touches in file_people_touches.get(path, {}).items():
299
- touches_by_person[person] += touches
300
- for person, recency in file_people_recency.get(path, {}).items():
301
- recency_by_person[person] += recency
302
- for person, weight in file_people_sensitive.get(path, {}).items():
303
- sensitive_by_person[person] += weight
304
-
305
- total_touches = sum(touches_by_person.values())
306
- total_recency = sum(recency_by_person.values())
307
- total_sensitive = sum(sensitive_by_person.values())
308
-
309
- ranked = sorted(touches_by_person.items(), key=lambda item: item[1], reverse=True)
310
- owners = []
311
- for person_id, touches in ranked[:top_n]:
312
- recency = recency_by_person.get(person_id, 0.0)
313
- sensitive = sensitive_by_person.get(person_id, 0.0)
314
- owners.append(
315
- {
316
- "person_id": person_id,
317
- "name": people.get(person_id, {}).get("name", person_id),
318
- "touches": touches,
319
- "touch_share": round(touches / total_touches, 4) if total_touches else 0.0,
320
- "recency_share": round(recency / total_recency, 4) if total_recency else 0.0,
321
- "sensitive_share": round(sensitive / total_sensitive, 4)
322
- if total_sensitive
323
- else 0.0,
324
- "primary_tz_offset": people.get(person_id, {}).get("primary_tz_offset", ""),
325
- }
326
- )
327
-
328
- return {
329
- "bus_factor": len(touches_by_person),
330
- "owner_count": len(touches_by_person),
331
- "totals": {
332
- "touches": total_touches,
333
- "recency_weight": round(total_recency, 6),
334
- "sensitive_weight": round(total_sensitive, 2),
335
- },
336
- "top_maintainers": owners,
337
- }
338
-
339
-
340
- def run_git_log(
341
- repo: str, since: str | None, until: str | None, include_merges: bool
342
- ) -> Iterable[list[str]]:
343
- cmd = [
344
- "git",
345
- "-C",
346
- repo,
347
- "log",
348
- "--name-only",
349
- "--no-renames",
350
- "--date=iso-strict",
351
- "--format=---%n%H%n%P%n%an%n%ae%n%ad%n%cn%n%ce%n%cd",
352
- ]
353
- if not include_merges:
354
- cmd.append("--no-merges")
355
- if since:
356
- cmd.extend(["--since", since])
357
- if until:
358
- cmd.extend(["--until", until])
359
-
360
- proc = subprocess.Popen(
361
- cmd,
362
- stdout=subprocess.PIPE,
363
- stderr=subprocess.PIPE,
364
- text=True,
365
- )
366
- assert proc.stdout is not None
367
-
368
- batch: list[str] = []
369
- for line in proc.stdout:
370
- batch.append(line.rstrip("\n"))
371
- if line.rstrip("\n") == "---" and len(batch) > 1:
372
- yield batch[:-1]
373
- batch = ["---"]
374
-
375
- if batch:
376
- yield batch
377
-
378
- stderr = proc.stderr.read() if proc.stderr else ""
379
- exit_code = proc.wait()
380
- if exit_code != 0:
381
- raise RuntimeError(stderr.strip() or "git log failed")
382
-
383
-
384
- def iter_commits(lines: Iterable[list[str]]) -> Iterable[tuple[dict[str, object], list[str]]]:
385
- for chunk in lines:
386
- if not chunk or chunk[0] != "---":
387
- continue
388
- header = chunk[1:9]
389
- if len(header) < 8:
390
- continue
391
- parents = [entry for entry in header[1].split(" ") if entry]
392
- commit = {
393
- "hash": header[0],
394
- "parents": parents,
395
- "is_merge": len(parents) > 1,
396
- "author_name": header[2],
397
- "author_email": header[3],
398
- "author_date": header[4],
399
- "committer_name": header[5],
400
- "committer_email": header[6],
401
- "committer_date": header[7],
402
- }
403
- files = [line for line in chunk[9:] if line.strip()]
404
- yield commit, files
405
-
406
-
407
- def ensure_out_dir(path: str) -> Path:
408
- out_dir = Path(path)
409
- out_dir.mkdir(parents=True, exist_ok=True)
410
- return out_dir
411
-
412
-
413
- def write_csv(path: Path, header: list[str], rows: Iterable[list[str]]) -> None:
414
- with path.open("w", encoding="utf-8", newline="") as handle:
415
- writer = csv.writer(handle)
416
- writer.writerow(header)
417
- for row in rows:
418
- writer.writerow(row)
419
-
420
-
421
- def build_ownership_map(args: argparse.Namespace) -> Path:
422
- now = dt.datetime.now(dt.timezone.utc)
423
- rules = load_sensitive_rules(args.sensitive_config)
424
- out_dir = ensure_out_dir(args.out)
425
-
426
- people: dict[str, dict[str, object]] = {}
427
- files: dict[str, dict[str, object]] = {}
428
- edges: dict[tuple[str, str], dict[str, object]] = {}
429
- file_people_touches: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
430
- file_people_recency: dict[str, dict[str, float]] = defaultdict(lambda: defaultdict(float))
431
- file_people_sensitive: dict[str, dict[str, float]] = defaultdict(lambda: defaultdict(float))
432
- tag_totals: dict[str, float] = defaultdict(float)
433
- tag_person_totals: dict[str, dict[str, float]] = defaultdict(lambda: defaultdict(float))
434
- person_timezone_counts: dict[str, dict[int, int]] = defaultdict(lambda: defaultdict(int))
435
- cochange_counts: dict[tuple[str, str], int] = defaultdict(int)
436
- cochange_file_commits: dict[str, int] = defaultdict(int)
437
- cochange_commits_used = 0
438
- cochange_commits_skipped = 0
439
- cochange_commits_filtered = 0
440
- cochange_files_excluded = 0
441
-
442
- commits_path = out_dir / "commits.jsonl"
443
- commit_handle = None
444
- if args.emit_commits:
445
- commit_handle = commits_path.open("w", encoding="utf-8")
446
-
447
- total_commits_seen = 0
448
- total_commits_included = 0
449
- commits_excluded_identities = 0
450
- commits_excluded_merges = 0
451
- total_edges = 0
452
-
453
- author_exclude_regexes = []
454
- if not args.no_default_author_excludes:
455
- author_exclude_regexes.extend(DEFAULT_AUTHOR_EXCLUDE_REGEXES)
456
- author_exclude_regexes.extend(args.author_exclude_regex)
457
- author_exclude_patterns = [
458
- re.compile(pattern, re.IGNORECASE) for pattern in author_exclude_regexes
459
- ]
460
-
461
- cochange_excludes = []
462
- if not args.no_default_cochange_excludes:
463
- cochange_excludes.extend(DEFAULT_COCHANGE_EXCLUDES)
464
- cochange_excludes.extend(args.cochange_exclude)
465
-
466
- log_lines = run_git_log(args.repo, args.since, args.until, args.include_merges)
467
- for commit, touched_files in iter_commits(log_lines):
468
- total_commits_seen += 1
469
-
470
- if commit.get("is_merge") and not args.include_merges:
471
- commits_excluded_merges += 1
472
- continue
473
-
474
- identity_name = commit.get(f"{args.identity}_name", "")
475
- identity_email = commit.get(f"{args.identity}_email", "")
476
- if author_excluded(
477
- identity_name,
478
- identity_email,
479
- author_exclude_patterns,
480
- ):
481
- commits_excluded_identities += 1
482
- continue
483
-
484
- if not touched_files:
485
- continue
486
-
487
- total_commits_included += 1
488
- if commit_handle:
489
- commit_handle.write(json.dumps({**commit, "files": touched_files}) + "\n")
490
-
491
- identity_name = commit.get(f"{args.identity}_name", "")
492
- identity_email = commit.get(f"{args.identity}_email", "") or identity_name
493
- commit_date = parse_date(commit.get(f"{args.date_field}_date", ""))
494
- recency = recency_weighted(now, commit_date, args.half_life_days)
495
- tz_minutes = offset_minutes(commit_date)
496
- if tz_minutes is not None:
497
- person_timezone_counts[identity_email][tz_minutes] += 1
498
- unique_files = sorted(set(touched_files))
499
- if not args.no_cochange and len(unique_files) > 1:
500
- if len(unique_files) > args.cochange_max_files:
501
- cochange_commits_skipped += 1
502
- else:
503
- filtered_files = [
504
- path for path in unique_files if not is_excluded(path, cochange_excludes)
505
- ]
506
- excluded = len(unique_files) - len(filtered_files)
507
- if excluded:
508
- cochange_files_excluded += excluded
509
- if len(filtered_files) < 2:
510
- cochange_commits_filtered += 1
511
- if filtered_files:
512
- for path in filtered_files:
513
- cochange_file_commits[path] += 1
514
- if len(filtered_files) >= 2:
515
- cochange_commits_used += 1
516
- for idx, path in enumerate(filtered_files):
517
- for other in filtered_files[idx + 1 :]:
518
- cochange_counts[(path, other)] += 1
519
-
520
- person = people.setdefault(
521
- identity_email,
522
- {
523
- "name": identity_name,
524
- "email": identity_email,
525
- "first_seen": commit_date,
526
- "last_seen": commit_date,
527
- "commit_count": 0,
528
- "touches": 0,
529
- "sensitive_touches": 0.0,
530
- },
531
- )
532
- person["commit_count"] = int(person["commit_count"]) + 1
533
- person["first_seen"] = min(person["first_seen"], commit_date)
534
- person["last_seen"] = max(person["last_seen"], commit_date)
535
-
536
- for path in touched_files:
537
- file_entry = files.setdefault(
538
- path,
539
- {
540
- "path": path,
541
- "first_seen": commit_date,
542
- "last_seen": commit_date,
543
- "commit_count": 0,
544
- "touches": 0,
545
- "authors": set(),
546
- "sensitive_tags": {},
547
- },
548
- )
549
- file_entry["commit_count"] = int(file_entry["commit_count"]) + 1
550
- file_entry["first_seen"] = min(file_entry["first_seen"], commit_date)
551
- file_entry["last_seen"] = max(file_entry["last_seen"], commit_date)
552
- file_entry["touches"] = int(file_entry["touches"]) + 1
553
- file_entry["authors"].add(identity_email)
554
-
555
- edge = edges.setdefault(
556
- (identity_email, path),
557
- {
558
- "touches": 0,
559
- "first_seen": commit_date,
560
- "last_seen": commit_date,
561
- "recency_weight": 0.0,
562
- "sensitive_weight": 0.0,
563
- },
564
- )
565
- edge["touches"] = int(edge["touches"]) + 1
566
- edge["first_seen"] = min(edge["first_seen"], commit_date)
567
- edge["last_seen"] = max(edge["last_seen"], commit_date)
568
- edge["recency_weight"] = float(edge["recency_weight"]) + recency
569
-
570
- tags = match_sensitive(path, rules)
571
- if tags:
572
- file_entry["sensitive_tags"] = tags
573
- sensitive_weight = sum(tags.values())
574
- edge["sensitive_weight"] = float(edge["sensitive_weight"]) + sensitive_weight
575
- person["sensitive_touches"] = float(person["sensitive_touches"]) + sensitive_weight
576
- file_people_sensitive[path][identity_email] += sensitive_weight
577
- for tag, weight in tags.items():
578
- tag_totals[tag] += weight
579
- tag_person_totals[tag][identity_email] += weight
580
-
581
- person["touches"] = int(person["touches"]) + 1
582
- file_people_touches[path][identity_email] += 1
583
- file_people_recency[path][identity_email] += recency
584
- total_edges += 1
585
-
586
- if commit_handle:
587
- commit_handle.close()
588
-
589
- people_rows = []
590
- for email, person in sorted(people.items()):
591
- tz_counts = person_timezone_counts.get(email, {})
592
- primary_tz_offset = ""
593
- primary_tz_minutes = ""
594
- timezone_offsets = ""
595
- if tz_counts:
596
- primary_tz_minutes_value = max(tz_counts.items(), key=lambda item: (item[1], item[0]))[
597
- 0
598
- ]
599
- primary_tz_offset = format_offset(primary_tz_minutes_value)
600
- primary_tz_minutes = str(primary_tz_minutes_value)
601
- timezone_offsets = ";".join(
602
- f"{format_offset(minutes)}:{count}"
603
- for minutes, count in sorted(tz_counts.items(), key=lambda item: item[0])
604
- )
605
- person["primary_tz_offset"] = primary_tz_offset
606
- people_rows.append(
607
- [
608
- email,
609
- str(person["name"]),
610
- email,
611
- person["first_seen"].isoformat(),
612
- person["last_seen"].isoformat(),
613
- str(person["commit_count"]),
614
- str(person["touches"]),
615
- f"{person['sensitive_touches']:.2f}",
616
- primary_tz_offset,
617
- primary_tz_minutes,
618
- timezone_offsets,
619
- ]
620
- )
621
-
622
- file_rows = []
623
- for path, file_entry in sorted(files.items()):
624
- authors = file_entry["authors"]
625
- bus_factor = len(authors)
626
- tags = file_entry["sensitive_tags"]
627
- tag_list = ";".join(sorted(tags.keys()))
628
- sensitivity_score = sum(tags.values()) if tags else 0.0
629
- file_rows.append(
630
- [
631
- path,
632
- path,
633
- file_entry["first_seen"].isoformat(),
634
- file_entry["last_seen"].isoformat(),
635
- str(file_entry["commit_count"]),
636
- str(file_entry["touches"]),
637
- str(bus_factor),
638
- f"{sensitivity_score:.2f}",
639
- tag_list,
640
- ]
641
- )
642
-
643
- edge_rows = []
644
- for (email, path), edge in edges.items():
645
- if int(edge["touches"]) < args.min_touches:
646
- continue
647
- edge_rows.append(
648
- [
649
- email,
650
- path,
651
- str(edge["touches"]),
652
- f"{edge['recency_weight']:.6f}",
653
- edge["first_seen"].isoformat(),
654
- edge["last_seen"].isoformat(),
655
- f"{edge['sensitive_weight']:.2f}",
656
- ]
657
- )
658
-
659
- cochange_rows: list[list[str]] = []
660
- if not args.no_cochange:
661
- for (file_a, file_b), count in cochange_counts.items():
662
- if count < args.cochange_min_count:
663
- continue
664
- commits_a = cochange_file_commits.get(file_a, 0)
665
- commits_b = cochange_file_commits.get(file_b, 0)
666
- denom = commits_a + commits_b - count
667
- if denom <= 0:
668
- continue
669
- jaccard = count / denom
670
- if jaccard < args.cochange_min_jaccard:
671
- continue
672
- cochange_rows.append([file_a, file_b, str(count), f"{jaccard:.6f}"])
673
-
674
- write_csv(
675
- out_dir / "people.csv",
676
- [
677
- "person_id",
678
- "name",
679
- "email",
680
- "first_seen",
681
- "last_seen",
682
- "commit_count",
683
- "touches",
684
- "sensitive_touches",
685
- "primary_tz_offset",
686
- "primary_tz_minutes",
687
- "timezone_offsets",
688
- ],
689
- people_rows,
690
- )
691
- write_csv(
692
- out_dir / "files.csv",
693
- [
694
- "file_id",
695
- "path",
696
- "first_seen",
697
- "last_seen",
698
- "commit_count",
699
- "touches",
700
- "bus_factor",
701
- "sensitivity_score",
702
- "sensitivity_tags",
703
- ],
704
- file_rows,
705
- )
706
- write_csv(
707
- out_dir / "edges.csv",
708
- [
709
- "person_id",
710
- "file_id",
711
- "touches",
712
- "recency_weight",
713
- "first_seen",
714
- "last_seen",
715
- "sensitive_weight",
716
- ],
717
- edge_rows,
718
- )
719
- if not args.no_cochange:
720
- write_csv(
721
- out_dir / "cochange_edges.csv",
722
- [
723
- "file_a",
724
- "file_b",
725
- "cochange_count",
726
- "jaccard",
727
- ],
728
- cochange_rows,
729
- )
730
-
731
- orphaned_sensitive_code = []
732
- bus_factor_hotspots = []
733
- for path, file_entry in files.items():
734
- tags = file_entry["sensitive_tags"]
735
- if not tags:
736
- continue
737
- bus_factor = len(file_entry["authors"])
738
- last_seen = file_entry["last_seen"]
739
- age_days = (now - last_seen).days
740
- top_owner = None
741
- if path in file_people_touches:
742
- top_owner = max(file_people_touches[path].items(), key=lambda item: item[1])[0]
743
- hotspot = {
744
- "path": path,
745
- "bus_factor": bus_factor,
746
- "last_touch": last_seen.isoformat(),
747
- "sensitivity_tags": sorted(tags.keys()),
748
- "top_owner": top_owner,
749
- }
750
- if bus_factor <= args.bus_factor_threshold:
751
- bus_factor_hotspots.append(hotspot)
752
- if age_days >= args.stale_days:
753
- orphaned_sensitive_code.append(
754
- {
755
- **hotspot,
756
- "last_security_touch": last_seen.isoformat(),
757
- }
758
- )
759
-
760
- hidden_owners = []
761
- for tag, total in tag_totals.items():
762
- if total <= 0:
763
- continue
764
- person_totals = tag_person_totals[tag]
765
- if not person_totals:
766
- continue
767
- top_email, top_value = max(person_totals.items(), key=lambda item: item[1])
768
- share = top_value / total
769
- if share >= args.owner_threshold:
770
- person_name = people.get(top_email, {}).get("name", top_email)
771
- hidden_owners.append(
772
- {
773
- "person": top_email,
774
- "name": person_name,
775
- "controls": f"{share * 100:.0f}% of {tag} code",
776
- "category": tag,
777
- "share": round(share, 4),
778
- }
779
- )
780
-
781
- summary = {
782
- "generated_at": now.isoformat(),
783
- "repo": os.path.abspath(args.repo),
784
- "parameters": {
785
- "since": args.since,
786
- "until": args.until,
787
- "half_life_days": args.half_life_days,
788
- "bus_factor_threshold": args.bus_factor_threshold,
789
- "stale_days": args.stale_days,
790
- "owner_threshold": args.owner_threshold,
791
- "sensitive_config": args.sensitive_config,
792
- "identity": args.identity,
793
- "date_field": args.date_field,
794
- "include_merges": args.include_merges,
795
- "cochange_enabled": not args.no_cochange,
796
- "cochange_max_files": args.cochange_max_files,
797
- "cochange_min_count": args.cochange_min_count,
798
- "cochange_min_jaccard": args.cochange_min_jaccard,
799
- "cochange_default_excludes": not args.no_default_cochange_excludes,
800
- "cochange_excludes": cochange_excludes,
801
- "author_default_excludes": not args.no_default_author_excludes,
802
- "author_exclude_regexes": author_exclude_regexes,
803
- "community_top_owners": args.community_top_owners,
804
- },
805
- "orphaned_sensitive_code": orphaned_sensitive_code,
806
- "hidden_owners": hidden_owners,
807
- "bus_factor_hotspots": bus_factor_hotspots,
808
- "stats": {
809
- "commits": total_commits_included,
810
- "commits_seen": total_commits_seen,
811
- "commits_excluded_identities": commits_excluded_identities,
812
- "commits_excluded_merges": commits_excluded_merges,
813
- "edges": total_edges,
814
- "people": len(people),
815
- "files": len(files),
816
- "cochange_pairs_total": len(cochange_counts) if not args.no_cochange else 0,
817
- "cochange_edges": len(cochange_rows) if not args.no_cochange else 0,
818
- "cochange_commits_used": cochange_commits_used if not args.no_cochange else 0,
819
- "cochange_commits_skipped": cochange_commits_skipped if not args.no_cochange else 0,
820
- "cochange_commits_filtered": cochange_commits_filtered if not args.no_cochange else 0,
821
- "cochange_files_excluded": cochange_files_excluded if not args.no_cochange else 0,
822
- },
823
- }
824
-
825
- with (out_dir / "summary.json").open("w", encoding="utf-8") as handle:
826
- json.dump(summary, handle, indent=2)
827
-
828
- if args.communities or args.graphml:
829
- try:
830
- import networkx as nx
831
- from networkx.algorithms import bipartite
832
- except ImportError:
833
- raise RuntimeError(
834
- "networkx is required for communities/graphml output. Install with: pip install networkx"
835
- )
836
- else:
837
- graph_bipartite = None
838
- graph_cochange = None
839
- person_nodes = set()
840
- file_nodes = set()
841
- community_index: dict[str, int] = {}
842
- community_metadata: list[dict[str, object]] = []
843
-
844
- if args.graphml or (args.communities and (args.no_cochange or not cochange_rows)):
845
- graph_bipartite = nx.Graph()
846
- for (email, path), edge in edges.items():
847
- if int(edge["touches"]) < args.min_touches:
848
- continue
849
- graph_bipartite.add_node(email, node_type="person")
850
- graph_bipartite.add_node(path, node_type="file")
851
- graph_bipartite.add_edge(email, path, weight=float(edge["touches"]))
852
- person_nodes.add(email)
853
- file_nodes.add(path)
854
-
855
- if not args.no_cochange and cochange_rows:
856
- graph_cochange = nx.Graph()
857
- for file_a, file_b, count, jaccard in cochange_rows:
858
- graph_cochange.add_edge(
859
- file_a,
860
- file_b,
861
- weight=float(jaccard),
862
- count=int(count),
863
- )
864
-
865
- if args.communities:
866
- communities_result = None
867
- if graph_cochange is not None:
868
- communities_result = list(
869
- nx.algorithms.community.greedy_modularity_communities(
870
- graph_cochange, weight="weight"
871
- )
872
- )
873
- elif graph_bipartite is not None and file_nodes:
874
- projected = bipartite.weighted_projected_graph(graph_bipartite, file_nodes)
875
- communities_result = list(
876
- nx.algorithms.community.greedy_modularity_communities(projected)
877
- )
878
-
879
- if communities_result is not None:
880
- serialized = []
881
- for idx, community in enumerate(communities_result, start=1):
882
- files_list = sorted(community)
883
- owners = compute_community_owners(
884
- files_list,
885
- people,
886
- file_people_touches,
887
- file_people_recency,
888
- file_people_sensitive,
889
- args.community_top_owners,
890
- )
891
- for path in files_list:
892
- community_index[path] = idx
893
- entry = {
894
- "id": idx,
895
- "size": len(files_list),
896
- "files": files_list[: args.max_community_files],
897
- "maintainers": owners["top_maintainers"],
898
- "bus_factor": owners["bus_factor"],
899
- "owner_count": owners["owner_count"],
900
- "totals": owners["totals"],
901
- }
902
- serialized.append(entry)
903
- metadata = dict(entry)
904
- metadata.pop("files", None)
905
- community_metadata.append(metadata)
906
- with (out_dir / "communities.json").open("w", encoding="utf-8") as handle:
907
- json.dump(serialized, handle, indent=2)
908
-
909
- if args.communities:
910
- for node, community_id in community_index.items():
911
- if graph_cochange is not None and node in graph_cochange:
912
- graph_cochange.nodes[node]["community_id"] = community_id
913
- if graph_bipartite is not None and node in graph_bipartite:
914
- graph_bipartite.nodes[node]["community_id"] = community_id
915
-
916
- graph_for_json = graph_cochange or graph_bipartite
917
- if graph_for_json is not None:
918
- try:
919
- from networkx.readwrite import json_graph
920
- except ImportError:
921
- pass
922
- else:
923
- data = json_graph.node_link_data(graph_for_json, edges="edges")
924
- data.setdefault("graph", {})
925
- data["graph"]["community_maintainers"] = community_metadata
926
- json_name = (
927
- "cochange.graph.json"
928
- if graph_for_json is graph_cochange
929
- else "ownership.graph.json"
930
- )
931
- with (out_dir / json_name).open("w", encoding="utf-8") as handle:
932
- json.dump(data, handle, indent=2)
933
-
934
- if args.graphml:
935
- if graph_bipartite is not None:
936
- nx.write_graphml(graph_bipartite, out_dir / "ownership.graphml")
937
- if graph_cochange is not None:
938
- nx.write_graphml(graph_cochange, out_dir / "cochange.graphml")
939
-
940
- return out_dir
941
-
942
-
943
- def main() -> int:
944
- args = parse_args()
945
- try:
946
- out_dir = build_ownership_map(args)
947
- except RuntimeError as exc:
948
- print(str(exc), file=sys.stderr)
949
- return 1
950
-
951
- print(f"Ownership map written to {out_dir}")
952
- return 0
953
-
954
-
955
- if __name__ == "__main__":
956
- raise SystemExit(main())