@oriro/orirocli 0.1.11 → 0.3.1

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 (1263) hide show
  1. package/ATTRIBUTION.md +53 -53
  2. package/LICENSE +21 -21
  3. package/README.md +10 -9
  4. package/dist/cli.js +1866 -190
  5. package/package.json +65 -64
  6. package/skills/1password/SKILL.md +118 -118
  7. package/skills/1password/references/cli-examples.md +29 -29
  8. package/skills/1password/references/get-started.md +21 -21
  9. package/skills/21stdev/SKILL.md +64 -64
  10. package/skills/algorithmic-art/LICENSE +21 -21
  11. package/skills/algorithmic-art/SKILL.md +446 -446
  12. package/skills/algorithmic-art/templates/generator_template.js +223 -223
  13. package/skills/algorithmic-art/templates/viewer.html +598 -598
  14. package/skills/apple-notes/SKILL.md +81 -81
  15. package/skills/apple-reminders/SKILL.md +122 -122
  16. package/skills/bear-notes/SKILL.md +111 -111
  17. package/skills/blogwatcher/SKILL.md +73 -73
  18. package/skills/blucli/SKILL.md +51 -51
  19. package/skills/brand-guidelines/LICENSE +21 -21
  20. package/skills/brand-guidelines/SKILL.md +76 -76
  21. package/skills/business/biz-analysis/LICENSE +21 -21
  22. package/skills/business/biz-analysis/SKILL.md +103 -103
  23. package/skills/business/biz-corporate-strategy/LICENSE +21 -21
  24. package/skills/business/biz-corporate-strategy/SKILL.md +76 -76
  25. package/skills/business/biz-customer-success/LICENSE +21 -21
  26. package/skills/business/biz-customer-success/SKILL.md +55 -55
  27. package/skills/business/biz-entrepreneurship/LICENSE +21 -21
  28. package/skills/business/biz-entrepreneurship/SKILL.md +72 -72
  29. package/skills/business/biz-hr/LICENSE +21 -21
  30. package/skills/business/biz-hr/SKILL.md +67 -67
  31. package/skills/business/biz-international/LICENSE +21 -21
  32. package/skills/business/biz-international/SKILL.md +51 -51
  33. package/skills/business/biz-leadership/LICENSE +21 -21
  34. package/skills/business/biz-leadership/SKILL.md +106 -106
  35. package/skills/business/biz-marketing-strategy/LICENSE +21 -21
  36. package/skills/business/biz-marketing-strategy/SKILL.md +119 -119
  37. package/skills/business/biz-negotiation/LICENSE +21 -21
  38. package/skills/business/biz-negotiation/SKILL.md +152 -152
  39. package/skills/business/biz-operations/LICENSE +21 -21
  40. package/skills/business/biz-operations/SKILL.md +74 -74
  41. package/skills/business/biz-project/LICENSE +21 -21
  42. package/skills/business/biz-project/SKILL.md +203 -203
  43. package/skills/business/biz-risk/LICENSE +21 -21
  44. package/skills/business/biz-risk/SKILL.md +85 -85
  45. package/skills/business/biz-sales/LICENSE +21 -21
  46. package/skills/business/biz-sales/SKILL.md +92 -92
  47. package/skills/business/biz-startup-ops/LICENSE +21 -21
  48. package/skills/business/biz-startup-ops/SKILL.md +70 -70
  49. package/skills/business/biz-strategy/LICENSE +21 -21
  50. package/skills/business/biz-strategy/SKILL.md +233 -233
  51. package/skills/business/biz-supply-chain-advanced/LICENSE +21 -21
  52. package/skills/business/biz-supply-chain-advanced/SKILL.md +68 -68
  53. package/skills/business/fin-chartered-exams/LICENSE +21 -21
  54. package/skills/business/fin-chartered-exams/SKILL.md +69 -69
  55. package/skills/camsnap/SKILL.md +49 -49
  56. package/skills/canvas/SKILL.md +82 -82
  57. package/skills/canvas-design/LICENSE +21 -21
  58. package/skills/canvas-design/SKILL.md +140 -140
  59. package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -93
  60. package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -93
  61. package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -93
  62. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -93
  63. package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -93
  64. package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -93
  65. package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -94
  66. package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -93
  67. package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -93
  68. package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -93
  69. package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -93
  70. package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -93
  71. package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -93
  72. package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -93
  73. package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -93
  74. package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -93
  75. package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -93
  76. package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -93
  77. package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -93
  78. package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -93
  79. package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -93
  80. package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -93
  81. package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -93
  82. package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -93
  83. package/skills/coding-agent/SKILL.md +146 -146
  84. package/skills/communication/comm-business-writing/LICENSE +21 -21
  85. package/skills/communication/comm-business-writing/SKILL.md +67 -67
  86. package/skills/communication/comm-cross-cultural/LICENSE +21 -21
  87. package/skills/communication/comm-cross-cultural/SKILL.md +88 -88
  88. package/skills/communication/comm-journalism/LICENSE +21 -21
  89. package/skills/communication/comm-journalism/SKILL.md +81 -81
  90. package/skills/communication/comm-linguistics/LICENSE +21 -21
  91. package/skills/communication/comm-linguistics/SKILL.md +82 -82
  92. package/skills/communication/comm-negotiation/LICENSE +21 -21
  93. package/skills/communication/comm-negotiation/SKILL.md +120 -120
  94. package/skills/communication/comm-presentations/LICENSE +21 -21
  95. package/skills/communication/comm-presentations/SKILL.md +93 -93
  96. package/skills/communication/comm-public-speaking/LICENSE +21 -21
  97. package/skills/communication/comm-public-speaking/SKILL.md +68 -68
  98. package/skills/communication/comm-writing/LICENSE +21 -21
  99. package/skills/communication/comm-writing/SKILL.md +69 -69
  100. package/skills/craft/ai-engineering/LICENSE +21 -21
  101. package/skills/craft/ai-engineering/SKILL.md +828 -828
  102. package/skills/craft/app-builder-guide/LICENSE +21 -21
  103. package/skills/craft/app-builder-guide/SKILL.md +332 -332
  104. package/skills/craft/become-an-ai-engineer-26/CONTRIBUTING.md +46 -46
  105. package/skills/craft/become-an-ai-engineer-26/LICENSE +21 -21
  106. package/skills/craft/become-an-ai-engineer-26/README.md +270 -270
  107. package/skills/craft/become-an-ai-engineer-26/SKILL.md +667 -667
  108. package/skills/craft/become-an-ai-engineer-26/community/BUILDS.md +13 -13
  109. package/skills/craft/become-an-ai-engineer-26/community/DISCUSSIONS.md +8 -8
  110. package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/README.md +14 -14
  111. package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/project/TEMPLATE.md +33 -33
  112. package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/README.md +25 -25
  113. package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/code/raw_loop.py +126 -126
  114. package/skills/craft/become-an-ai-engineer-26/phases/phase-2-architecture/README.md +17 -17
  115. package/skills/craft/become-an-ai-engineer-26/phases/phase-3-harness/README.md +17 -17
  116. package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/README.md +21 -21
  117. package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/code/.github/workflows/eval.yml +40 -40
  118. package/skills/craft/become-an-ai-engineer-26/phases/phase-5-production/README.md +16 -16
  119. package/skills/craft/become-an-ai-engineer-26/projects/1-mobile-app-slm/README.md +11 -11
  120. package/skills/craft/become-an-ai-engineer-26/projects/2-self-improving-coder/README.md +11 -11
  121. package/skills/craft/become-an-ai-engineer-26/projects/3-video-editor-agent/README.md +11 -11
  122. package/skills/craft/become-an-ai-engineer-26/projects/4-personal-life-os/README.md +12 -12
  123. package/skills/craft/become-an-ai-engineer-26/projects/5-enterprise-workflow/README.md +12 -12
  124. package/skills/craft/become-an-ai-engineer-26/references/benchmark-numbers.md +41 -41
  125. package/skills/craft/become-an-ai-engineer-26/references/mhc-stable-training.md +73 -73
  126. package/skills/craft/become-an-ai-engineer-26/references/stack-decisions.md +37 -37
  127. package/skills/craft/become-an-ai-engineer-26/references/yarn-context-extension.md +123 -123
  128. package/skills/craft/codex-result-handling/LICENSE +21 -21
  129. package/skills/craft/codex-result-handling/SKILL.md +26 -26
  130. package/skills/craft/debug-and-build-methodology/LICENSE +21 -21
  131. package/skills/craft/debug-and-build-methodology/SKILL.md +432 -432
  132. package/skills/craft/design/LICENSE +21 -21
  133. package/skills/craft/design/SKILL.md +274 -274
  134. package/skills/craft/dev/LICENSE +21 -21
  135. package/skills/craft/dev/SKILL.md +12 -12
  136. package/skills/craft/dev/release.md +85 -85
  137. package/skills/craft/dev/roll.md +50 -50
  138. package/skills/craft/doc-coauthoring/LICENSE +21 -21
  139. package/skills/craft/doc-coauthoring/SKILL.md +397 -397
  140. package/skills/craft/focus/LICENSE +21 -21
  141. package/skills/craft/focus/SKILL.md +432 -432
  142. package/skills/craft/focus/UPSTREAM_README.md +233 -233
  143. package/skills/craft/gh/LICENSE +21 -21
  144. package/skills/craft/gh/SKILL.md +84 -84
  145. package/skills/craft/gh-skill/LICENSE +21 -21
  146. package/skills/craft/gh-skill/SKILL.md +121 -121
  147. package/skills/craft/godmode/LICENSE +21 -21
  148. package/skills/craft/godmode/SKILL.md +87 -87
  149. package/skills/craft/godmode/references/android-launch.md +680 -680
  150. package/skills/craft/godmode/references/data-gcp.md +1038 -1038
  151. package/skills/craft/godmode/references/expo-eas.md +816 -816
  152. package/skills/craft/godmode/references/ios-launch.md +734 -734
  153. package/skills/craft/google-ai-latest/LICENSE +21 -21
  154. package/skills/craft/google-ai-latest/SKILL.md +682 -682
  155. package/skills/craft/gpt-5-4-prompting/LICENSE +21 -21
  156. package/skills/craft/gpt-5-4-prompting/SKILL.md +63 -63
  157. package/skills/craft/gpt-5-4-prompting/references/codex-prompt-antipatterns.md +101 -101
  158. package/skills/craft/gpt-5-4-prompting/references/codex-prompt-recipes.md +150 -150
  159. package/skills/craft/gpt-5-4-prompting/references/prompt-blocks.md +172 -172
  160. package/skills/craft/grill-me/LICENSE +21 -21
  161. package/skills/craft/grill-me/SKILL.md +13 -13
  162. package/skills/craft/idea-to-deploy/LICENSE +21 -21
  163. package/skills/craft/idea-to-deploy/SKILL.md +292 -292
  164. package/skills/craft/idea-to-deploy/references/auth-playbook.md +195 -195
  165. package/skills/craft/idea-to-deploy/references/gcp-deployment.md +268 -268
  166. package/skills/craft/idea-to-deploy/references/stack-selection.md +117 -117
  167. package/skills/craft/image-generation-engineer/LICENSE +21 -21
  168. package/skills/craft/image-generation-engineer/SKILL.md +183 -183
  169. package/skills/craft/image-generation-engineer/references/architectures.md +260 -260
  170. package/skills/craft/image-generation-engineer/references/foundations.md +107 -107
  171. package/skills/craft/image-generation-engineer/references/inference-and-serving.md +253 -253
  172. package/skills/craft/image-generation-engineer/references/training.md +149 -149
  173. package/skills/craft/marketing/LICENSE +21 -21
  174. package/skills/craft/marketing/SKILL.md +1954 -1954
  175. package/skills/craft/master-architect/LICENSE +21 -21
  176. package/skills/craft/master-architect/SKILL.md +361 -361
  177. package/skills/craft/master-architect/references/ai-ml.md +317 -317
  178. package/skills/craft/master-architect/references/architecture.md +268 -268
  179. package/skills/craft/master-architect/references/auth-playbook.md +195 -195
  180. package/skills/craft/master-architect/references/cloud.md +323 -323
  181. package/skills/craft/master-architect/references/cyber.md +839 -839
  182. package/skills/craft/master-architect/references/data-eng.md +366 -366
  183. package/skills/craft/master-architect/references/devops.md +550 -550
  184. package/skills/craft/master-architect/references/gcp-deployment.md +268 -268
  185. package/skills/craft/master-architect/references/languages.md +748 -748
  186. package/skills/craft/master-architect/references/legacy.md +240 -240
  187. package/skills/craft/master-architect/references/mobile.md +447 -447
  188. package/skills/craft/master-architect/references/patterns.md +451 -451
  189. package/skills/craft/master-architect/references/saas-patterns.md +379 -379
  190. package/skills/craft/master-architect/references/sdlc.md +349 -349
  191. package/skills/craft/master-architect/references/stack-selection.md +117 -117
  192. package/skills/craft/oriro-ui-2026/LICENSE +21 -21
  193. package/skills/craft/oriro-ui-2026/SKILL.md +329 -329
  194. package/skills/craft/playwright-cli/LICENSE +21 -21
  195. package/skills/craft/playwright-cli/SKILL.md +393 -393
  196. package/skills/craft/playwright-cli/references/element-attributes.md +23 -23
  197. package/skills/craft/playwright-cli/references/playwright-tests.md +39 -39
  198. package/skills/craft/playwright-cli/references/request-mocking.md +87 -87
  199. package/skills/craft/playwright-cli/references/running-code.md +240 -240
  200. package/skills/craft/playwright-cli/references/session-management.md +226 -226
  201. package/skills/craft/playwright-cli/references/spec-driven-testing.md +312 -312
  202. package/skills/craft/playwright-cli/references/storage-state.md +275 -275
  203. package/skills/craft/playwright-cli/references/test-generation.md +134 -134
  204. package/skills/craft/playwright-cli/references/tracing.md +142 -142
  205. package/skills/craft/playwright-cli/references/video-recording.md +150 -150
  206. package/skills/craft/remotion-best-practices/LICENSE +21 -21
  207. package/skills/craft/remotion-best-practices/SKILL.md +345 -345
  208. package/skills/craft/remotion-best-practices/rules/3d.md +86 -86
  209. package/skills/craft/remotion-best-practices/rules/assets/charts-bar-chart.tsx +165 -165
  210. package/skills/craft/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +89 -89
  211. package/skills/craft/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +101 -101
  212. package/skills/craft/remotion-best-practices/rules/audio-visualization.md +195 -195
  213. package/skills/craft/remotion-best-practices/rules/audio.md +167 -167
  214. package/skills/craft/remotion-best-practices/rules/calculate-metadata.md +118 -118
  215. package/skills/craft/remotion-best-practices/rules/compositions.md +132 -132
  216. package/skills/craft/remotion-best-practices/rules/display-captions.md +176 -176
  217. package/skills/craft/remotion-best-practices/rules/ffmpeg.md +34 -34
  218. package/skills/craft/remotion-best-practices/rules/get-audio-duration.md +58 -58
  219. package/skills/craft/remotion-best-practices/rules/get-video-dimensions.md +68 -68
  220. package/skills/craft/remotion-best-practices/rules/get-video-duration.md +60 -60
  221. package/skills/craft/remotion-best-practices/rules/gifs.md +135 -135
  222. package/skills/craft/remotion-best-practices/rules/google-fonts.md +72 -72
  223. package/skills/craft/remotion-best-practices/rules/html-in-canvas.md +122 -122
  224. package/skills/craft/remotion-best-practices/rules/images.md +67 -67
  225. package/skills/craft/remotion-best-practices/rules/import-srt-captions.md +69 -69
  226. package/skills/craft/remotion-best-practices/rules/light-leaks.md +73 -73
  227. package/skills/craft/remotion-best-practices/rules/local-fonts.md +65 -65
  228. package/skills/craft/remotion-best-practices/rules/lottie.md +67 -67
  229. package/skills/craft/remotion-best-practices/rules/maplibre.md +441 -441
  230. package/skills/craft/remotion-best-practices/rules/measuring-dom-nodes.md +34 -34
  231. package/skills/craft/remotion-best-practices/rules/measuring-text.md +140 -140
  232. package/skills/craft/remotion-best-practices/rules/parameters.md +109 -109
  233. package/skills/craft/remotion-best-practices/rules/sequencing.md +144 -144
  234. package/skills/craft/remotion-best-practices/rules/sfx.md +30 -30
  235. package/skills/craft/remotion-best-practices/rules/silence-detection.md +73 -73
  236. package/skills/craft/remotion-best-practices/rules/subtitles.md +36 -36
  237. package/skills/craft/remotion-best-practices/rules/tailwind.md +11 -11
  238. package/skills/craft/remotion-best-practices/rules/text-animations.md +20 -20
  239. package/skills/craft/remotion-best-practices/rules/timing.md +130 -130
  240. package/skills/craft/remotion-best-practices/rules/transcribe-captions.md +70 -70
  241. package/skills/craft/remotion-best-practices/rules/transitions.md +193 -193
  242. package/skills/craft/remotion-best-practices/rules/transparent-videos.md +102 -102
  243. package/skills/craft/remotion-best-practices/rules/trimming.md +51 -51
  244. package/skills/craft/remotion-best-practices/rules/videos.md +169 -169
  245. package/skills/craft/remotion-best-practices/rules/voiceover.md +94 -94
  246. package/skills/craft/supabase-postgres-best-practices/CHANGELOG.md +25 -25
  247. package/skills/craft/supabase-postgres-best-practices/LICENSE +21 -21
  248. package/skills/craft/supabase-postgres-best-practices/SKILL.md +69 -69
  249. package/skills/craft/supabase-postgres-best-practices/references/_contributing.md +166 -166
  250. package/skills/craft/supabase-postgres-best-practices/references/_sections.md +47 -47
  251. package/skills/craft/supabase-postgres-best-practices/references/_template.md +34 -34
  252. package/skills/craft/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -55
  253. package/skills/craft/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -49
  254. package/skills/craft/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -46
  255. package/skills/craft/supabase-postgres-best-practices/references/conn-limits.md +44 -44
  256. package/skills/craft/supabase-postgres-best-practices/references/conn-pooling.md +41 -41
  257. package/skills/craft/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -46
  258. package/skills/craft/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -54
  259. package/skills/craft/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -53
  260. package/skills/craft/supabase-postgres-best-practices/references/data-pagination.md +50 -50
  261. package/skills/craft/supabase-postgres-best-practices/references/data-upsert.md +50 -50
  262. package/skills/craft/supabase-postgres-best-practices/references/lock-advisory.md +56 -56
  263. package/skills/craft/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -68
  264. package/skills/craft/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -50
  265. package/skills/craft/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -54
  266. package/skills/craft/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -45
  267. package/skills/craft/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -55
  268. package/skills/craft/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -55
  269. package/skills/craft/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -44
  270. package/skills/craft/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -40
  271. package/skills/craft/supabase-postgres-best-practices/references/query-index-types.md +48 -48
  272. package/skills/craft/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -43
  273. package/skills/craft/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -45
  274. package/skills/craft/supabase-postgres-best-practices/references/schema-constraints.md +80 -80
  275. package/skills/craft/supabase-postgres-best-practices/references/schema-data-types.md +46 -46
  276. package/skills/craft/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -59
  277. package/skills/craft/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -55
  278. package/skills/craft/supabase-postgres-best-practices/references/schema-partitioning.md +55 -55
  279. package/skills/craft/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -61
  280. package/skills/craft/supabase-postgres-best-practices/references/security-privileges.md +54 -54
  281. package/skills/craft/supabase-postgres-best-practices/references/security-rls-basics.md +50 -50
  282. package/skills/craft/supabase-postgres-best-practices/references/security-rls-performance.md +63 -63
  283. package/skills/craft/uipm-banner-design/LICENSE +21 -21
  284. package/skills/craft/uipm-banner-design/SKILL.md +201 -201
  285. package/skills/craft/uipm-banner-design/references/banner-sizes-and-styles.md +129 -129
  286. package/skills/craft/uipm-brand/LICENSE +21 -21
  287. package/skills/craft/uipm-brand/SKILL.md +104 -104
  288. package/skills/craft/uipm-brand/references/approval-checklist.md +184 -184
  289. package/skills/craft/uipm-brand/references/asset-organization.md +167 -167
  290. package/skills/craft/uipm-brand/references/brand-guideline-template.md +161 -161
  291. package/skills/craft/uipm-brand/references/color-palette-management.md +203 -203
  292. package/skills/craft/uipm-brand/references/consistency-checklist.md +105 -105
  293. package/skills/craft/uipm-brand/references/logo-usage-rules.md +204 -204
  294. package/skills/craft/uipm-brand/references/messaging-framework.md +91 -91
  295. package/skills/craft/uipm-brand/references/typography-specifications.md +265 -265
  296. package/skills/craft/uipm-brand/references/update.md +128 -128
  297. package/skills/craft/uipm-brand/references/visual-identity.md +109 -109
  298. package/skills/craft/uipm-brand/references/voice-framework.md +99 -99
  299. package/skills/craft/uipm-brand/scripts/extract-colors.cjs +333 -333
  300. package/skills/craft/uipm-brand/scripts/inject-brand-context.cjs +324 -324
  301. package/skills/craft/uipm-brand/scripts/sync-brand-to-tokens.cjs +269 -269
  302. package/skills/craft/uipm-brand/scripts/validate-asset.cjs +361 -361
  303. package/skills/craft/uipm-brand/templates/brand-guidelines-starter.md +280 -280
  304. package/skills/craft/uipm-design/LICENSE +21 -21
  305. package/skills/craft/uipm-design/SKILL.md +305 -305
  306. package/skills/craft/uipm-design/data/cip/deliverables.csv +50 -50
  307. package/skills/craft/uipm-design/data/cip/industries.csv +20 -20
  308. package/skills/craft/uipm-design/data/cip/mockup-contexts.csv +20 -20
  309. package/skills/craft/uipm-design/data/cip/styles.csv +20 -20
  310. package/skills/craft/uipm-design/data/icon/styles.csv +16 -16
  311. package/skills/craft/uipm-design/data/logo/colors.csv +56 -56
  312. package/skills/craft/uipm-design/data/logo/industries.csv +56 -56
  313. package/skills/craft/uipm-design/data/logo/styles.csv +56 -56
  314. package/skills/craft/uipm-design/references/banner-sizes-and-styles.md +129 -129
  315. package/skills/craft/uipm-design/references/cip-deliverable-guide.md +111 -111
  316. package/skills/craft/uipm-design/references/cip-design.md +121 -121
  317. package/skills/craft/uipm-design/references/cip-prompt-engineering.md +94 -94
  318. package/skills/craft/uipm-design/references/cip-style-guide.md +76 -76
  319. package/skills/craft/uipm-design/references/design-routing.md +226 -226
  320. package/skills/craft/uipm-design/references/icon-design.md +122 -122
  321. package/skills/craft/uipm-design/references/logo-color-psychology.md +113 -113
  322. package/skills/craft/uipm-design/references/logo-design.md +92 -92
  323. package/skills/craft/uipm-design/references/logo-prompt-engineering.md +176 -176
  324. package/skills/craft/uipm-design/references/logo-style-guide.md +129 -129
  325. package/skills/craft/uipm-design/references/slides-copywriting-formulas.md +92 -92
  326. package/skills/craft/uipm-design/references/slides-create.md +5 -5
  327. package/skills/craft/uipm-design/references/slides-html-template.md +374 -374
  328. package/skills/craft/uipm-design/references/slides-layout-patterns.md +155 -155
  329. package/skills/craft/uipm-design/references/slides-strategies.md +97 -97
  330. package/skills/craft/uipm-design/references/slides.md +42 -42
  331. package/skills/craft/uipm-design/references/social-photos-design.md +353 -353
  332. package/skills/craft/uipm-design/scripts/cip/core.py +215 -215
  333. package/skills/craft/uipm-design/scripts/cip/generate.py +484 -484
  334. package/skills/craft/uipm-design/scripts/cip/render-html.py +424 -424
  335. package/skills/craft/uipm-design/scripts/cip/search.py +127 -127
  336. package/skills/craft/uipm-design/scripts/icon/generate.py +487 -487
  337. package/skills/craft/uipm-design/scripts/logo/core.py +175 -175
  338. package/skills/craft/uipm-design/scripts/logo/generate.py +362 -362
  339. package/skills/craft/uipm-design/scripts/logo/search.py +114 -114
  340. package/skills/craft/uipm-design-system/LICENSE +21 -21
  341. package/skills/craft/uipm-design-system/SKILL.md +255 -255
  342. package/skills/craft/uipm-design-system/data/slide-backgrounds.csv +11 -11
  343. package/skills/craft/uipm-design-system/data/slide-charts.csv +26 -26
  344. package/skills/craft/uipm-design-system/data/slide-color-logic.csv +14 -14
  345. package/skills/craft/uipm-design-system/data/slide-copy.csv +26 -26
  346. package/skills/craft/uipm-design-system/data/slide-layout-logic.csv +16 -16
  347. package/skills/craft/uipm-design-system/data/slide-layouts.csv +26 -26
  348. package/skills/craft/uipm-design-system/data/slide-strategies.csv +16 -16
  349. package/skills/craft/uipm-design-system/data/slide-typography.csv +15 -15
  350. package/skills/craft/uipm-design-system/references/component-specs.md +236 -236
  351. package/skills/craft/uipm-design-system/references/component-tokens.md +214 -214
  352. package/skills/craft/uipm-design-system/references/primitive-tokens.md +199 -199
  353. package/skills/craft/uipm-design-system/references/semantic-tokens.md +215 -215
  354. package/skills/craft/uipm-design-system/references/states-and-variants.md +243 -243
  355. package/skills/craft/uipm-design-system/references/tailwind-integration.md +257 -257
  356. package/skills/craft/uipm-design-system/references/token-architecture.md +226 -226
  357. package/skills/craft/uipm-design-system/scripts/embed-tokens.cjs +97 -97
  358. package/skills/craft/uipm-design-system/scripts/fetch-background.py +317 -317
  359. package/skills/craft/uipm-design-system/scripts/generate-slide.py +753 -753
  360. package/skills/craft/uipm-design-system/scripts/generate-tokens.cjs +213 -213
  361. package/skills/craft/uipm-design-system/scripts/html-token-validator.py +327 -327
  362. package/skills/craft/uipm-design-system/scripts/search-slides.py +218 -218
  363. package/skills/craft/uipm-design-system/scripts/slide-token-validator.py +35 -35
  364. package/skills/craft/uipm-design-system/scripts/slide_search_core.py +453 -453
  365. package/skills/craft/uipm-design-system/scripts/validate-tokens.cjs +254 -254
  366. package/skills/craft/uipm-design-system/templates/design-tokens-starter.json +143 -143
  367. package/skills/craft/uipm-slides/LICENSE +21 -21
  368. package/skills/craft/uipm-slides/SKILL.md +45 -45
  369. package/skills/craft/uipm-slides/references/copywriting-formulas.md +92 -92
  370. package/skills/craft/uipm-slides/references/create.md +5 -5
  371. package/skills/craft/uipm-slides/references/html-template.md +374 -374
  372. package/skills/craft/uipm-slides/references/layout-patterns.md +155 -155
  373. package/skills/craft/uipm-slides/references/slide-strategies.md +97 -97
  374. package/skills/craft/uipm-ui-ux-pro-max/LICENSE +21 -21
  375. package/skills/craft/uipm-ui-ux-pro-max/SKILL.md +678 -678
  376. package/skills/craft/uipm-ui-ux-pro-max/data/_sync_all.py +414 -414
  377. package/skills/craft/uipm-ui-ux-pro-max/data/app-interface.csv +30 -30
  378. package/skills/craft/uipm-ui-ux-pro-max/data/charts.csv +26 -26
  379. package/skills/craft/uipm-ui-ux-pro-max/data/colors.csv +161 -161
  380. package/skills/craft/uipm-ui-ux-pro-max/data/design.csv +1775 -1775
  381. package/skills/craft/uipm-ui-ux-pro-max/data/draft.csv +1778 -1778
  382. package/skills/craft/uipm-ui-ux-pro-max/data/google-fonts.csv +1924 -1924
  383. package/skills/craft/uipm-ui-ux-pro-max/data/icons.csv +105 -105
  384. package/skills/craft/uipm-ui-ux-pro-max/data/landing.csv +35 -35
  385. package/skills/craft/uipm-ui-ux-pro-max/data/products.csv +162 -162
  386. package/skills/craft/uipm-ui-ux-pro-max/data/react-performance.csv +45 -45
  387. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/angular.csv +51 -51
  388. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/astro.csv +54 -54
  389. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/flutter.csv +53 -53
  390. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
  391. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
  392. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/laravel.csv +51 -51
  393. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
  394. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
  395. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
  396. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  397. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react.csv +54 -54
  398. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
  399. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/svelte.csv +54 -54
  400. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
  401. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/threejs.csv +54 -54
  402. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/vue.csv +50 -50
  403. package/skills/craft/uipm-ui-ux-pro-max/data/styles.csv +85 -85
  404. package/skills/craft/uipm-ui-ux-pro-max/data/typography.csv +74 -74
  405. package/skills/craft/uipm-ui-ux-pro-max/data/ui-reasoning.csv +162 -162
  406. package/skills/craft/uipm-ui-ux-pro-max/data/ux-guidelines.csv +99 -99
  407. package/skills/craft/uipm-ui-ux-pro-max/scripts/core.py +262 -262
  408. package/skills/craft/uipm-ui-ux-pro-max/scripts/design_system.py +1148 -1148
  409. package/skills/craft/uipm-ui-ux-pro-max/scripts/search.py +114 -114
  410. package/skills/craft/uipm-ui-ux-pro-max/templates/base/quick-reference.md +297 -297
  411. package/skills/craft/uipm-ui-ux-pro-max/templates/base/skill-content.md +375 -375
  412. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/agent.json +21 -21
  413. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/augment.json +18 -18
  414. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/claude.json +21 -21
  415. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codebuddy.json +21 -21
  416. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codex.json +21 -21
  417. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/continue.json +21 -21
  418. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/copilot.json +21 -21
  419. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/cursor.json +21 -21
  420. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/droid.json +21 -21
  421. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/gemini.json +21 -21
  422. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kilocode.json +21 -21
  423. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kiro.json +21 -21
  424. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/opencode.json +21 -21
  425. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/qoder.json +21 -21
  426. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/roocode.json +21 -21
  427. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/trae.json +21 -21
  428. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/warp.json +18 -18
  429. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/windsurf.json +21 -21
  430. package/skills/craft/vercel-optimize/AGENTS.md +48 -48
  431. package/skills/craft/vercel-optimize/CONTRIBUTING.md +41 -41
  432. package/skills/craft/vercel-optimize/LICENSE +21 -21
  433. package/skills/craft/vercel-optimize/README.md +91 -91
  434. package/skills/craft/vercel-optimize/SKILL.md +325 -325
  435. package/skills/craft/vercel-optimize/lib/auth-route.mjs +23 -23
  436. package/skills/craft/vercel-optimize/lib/budget-summary.mjs +208 -208
  437. package/skills/craft/vercel-optimize/lib/citations.mjs +147 -147
  438. package/skills/craft/vercel-optimize/lib/cost-coverage.mjs +162 -162
  439. package/skills/craft/vercel-optimize/lib/dedup-recs.mjs +340 -340
  440. package/skills/craft/vercel-optimize/lib/deep-dive.mjs +371 -371
  441. package/skills/craft/vercel-optimize/lib/display-labels.mjs +219 -219
  442. package/skills/craft/vercel-optimize/lib/extract-claims.mjs +640 -640
  443. package/skills/craft/vercel-optimize/lib/framework-support.mjs +69 -69
  444. package/skills/craft/vercel-optimize/lib/gates/build-minutes-fanout.mjs +73 -73
  445. package/skills/craft/vercel-optimize/lib/gates/cold-start.mjs +72 -72
  446. package/skills/craft/vercel-optimize/lib/gates/contract.mjs +82 -82
  447. package/skills/craft/vercel-optimize/lib/gates/cwv-poor.mjs +95 -95
  448. package/skills/craft/vercel-optimize/lib/gates/external-api-slow.mjs +60 -60
  449. package/skills/craft/vercel-optimize/lib/gates/hard-gates.mjs +70 -70
  450. package/skills/craft/vercel-optimize/lib/gates/index.mjs +45 -45
  451. package/skills/craft/vercel-optimize/lib/gates/isr-overrevalidation.mjs +62 -62
  452. package/skills/craft/vercel-optimize/lib/gates/middleware-heavy.mjs +53 -53
  453. package/skills/craft/vercel-optimize/lib/gates/observability-events-attribution.mjs +58 -58
  454. package/skills/craft/vercel-optimize/lib/gates/platform-bot-protection.mjs +123 -123
  455. package/skills/craft/vercel-optimize/lib/gates/platform-fluid-compute.mjs +94 -94
  456. package/skills/craft/vercel-optimize/lib/gates/region-misconfig.mjs +71 -71
  457. package/skills/craft/vercel-optimize/lib/gates/route-errors.mjs +95 -95
  458. package/skills/craft/vercel-optimize/lib/gates/scanner-driven.mjs +150 -150
  459. package/skills/craft/vercel-optimize/lib/gates/select-candidates.mjs +137 -137
  460. package/skills/craft/vercel-optimize/lib/gates/slow-route.mjs +97 -97
  461. package/skills/craft/vercel-optimize/lib/gates/types.d.ts +38 -38
  462. package/skills/craft/vercel-optimize/lib/gates/uncached-route.mjs +103 -103
  463. package/skills/craft/vercel-optimize/lib/gates/usage-spike-triage.mjs +122 -122
  464. package/skills/craft/vercel-optimize/lib/grade-recommendation.mjs +170 -170
  465. package/skills/craft/vercel-optimize/lib/impact-label.mjs +128 -128
  466. package/skills/craft/vercel-optimize/lib/impact-magnitude.mjs +66 -66
  467. package/skills/craft/vercel-optimize/lib/investigation-brief.mjs +751 -751
  468. package/skills/craft/vercel-optimize/lib/observation-safety.mjs +217 -217
  469. package/skills/craft/vercel-optimize/lib/project-facts.mjs +101 -101
  470. package/skills/craft/vercel-optimize/lib/queries.mjs +333 -333
  471. package/skills/craft/vercel-optimize/lib/reconcile-candidates.mjs +388 -388
  472. package/skills/craft/vercel-optimize/lib/render-report.mjs +1065 -1065
  473. package/skills/craft/vercel-optimize/lib/repo-root.mjs +97 -97
  474. package/skills/craft/vercel-optimize/lib/route-normalize.mjs +224 -224
  475. package/skills/craft/vercel-optimize/lib/sanitizers/bot-protection-certainty.mjs +56 -56
  476. package/skills/craft/vercel-optimize/lib/sanitizers/cache-tag-invalidation-certainty.mjs +33 -33
  477. package/skills/craft/vercel-optimize/lib/sanitizers/count-correct.mjs +53 -53
  478. package/skills/craft/vercel-optimize/lib/sanitizers/function-duration-invocations.mjs +32 -32
  479. package/skills/craft/vercel-optimize/lib/sanitizers/index.mjs +87 -87
  480. package/skills/craft/vercel-optimize/lib/sanitizers/middleware-conflict.mjs +37 -37
  481. package/skills/craft/vercel-optimize/lib/sanitizers/missing-citation.mjs +16 -16
  482. package/skills/craft/vercel-optimize/lib/sanitizers/pre-release.mjs +75 -75
  483. package/skills/craft/vercel-optimize/lib/sanitizers/rate-limit.mjs +73 -73
  484. package/skills/craft/vercel-optimize/lib/sanitizers/rendering-mode-mislabel.mjs +42 -42
  485. package/skills/craft/vercel-optimize/lib/sanitizers/undeclared-dep.mjs +110 -110
  486. package/skills/craft/vercel-optimize/lib/sanitizers/vercel-directive-strip.mjs +37 -37
  487. package/skills/craft/vercel-optimize/lib/sanitizers/window-units.mjs +26 -26
  488. package/skills/craft/vercel-optimize/lib/scanners/cache-components-suspense-dedupe.mjs +114 -114
  489. package/skills/craft/vercel-optimize/lib/scanners/edge-heavy-import.mjs +102 -102
  490. package/skills/craft/vercel-optimize/lib/scanners/force-dynamic.mjs +39 -39
  491. package/skills/craft/vercel-optimize/lib/scanners/headers-in-page.mjs +43 -43
  492. package/skills/craft/vercel-optimize/lib/scanners/index.mjs +35 -35
  493. package/skills/craft/vercel-optimize/lib/scanners/large-static-asset.mjs +93 -93
  494. package/skills/craft/vercel-optimize/lib/scanners/max-age-without-s-maxage.mjs +47 -47
  495. package/skills/craft/vercel-optimize/lib/scanners/middleware-broad-matcher.mjs +53 -53
  496. package/skills/craft/vercel-optimize/lib/scanners/missing-cache-headers.mjs +97 -97
  497. package/skills/craft/vercel-optimize/lib/scanners/prisma-include-tree.mjs +39 -39
  498. package/skills/craft/vercel-optimize/lib/scanners/region-pin-in-config.mjs +89 -89
  499. package/skills/craft/vercel-optimize/lib/scanners/source-maps-production.mjs +33 -33
  500. package/skills/craft/vercel-optimize/lib/scanners/sveltekit-prerender-missing.mjs +47 -47
  501. package/skills/craft/vercel-optimize/lib/scanners/turbo-force-bypass.mjs +136 -136
  502. package/skills/craft/vercel-optimize/lib/scanners/unoptimized-image.mjs +127 -127
  503. package/skills/craft/vercel-optimize/lib/scanners/use-cache-date-stamp.mjs +112 -112
  504. package/skills/craft/vercel-optimize/lib/support-topics.mjs +365 -365
  505. package/skills/craft/vercel-optimize/lib/throttle.mjs +280 -280
  506. package/skills/craft/vercel-optimize/lib/util.mjs +17 -17
  507. package/skills/craft/vercel-optimize/lib/vercel.mjs +855 -855
  508. package/skills/craft/vercel-optimize/lib/verify-claim.mjs +1843 -1843
  509. package/skills/craft/vercel-optimize/lib/workspace-resolver.mjs +552 -552
  510. package/skills/craft/vercel-optimize/metadata.json +14 -14
  511. package/skills/craft/vercel-optimize/references/candidates.md +176 -176
  512. package/skills/craft/vercel-optimize/references/data-collection.md +224 -224
  513. package/skills/craft/vercel-optimize/references/docs-library.json +683 -683
  514. package/skills/craft/vercel-optimize/references/doctrine.md +108 -108
  515. package/skills/craft/vercel-optimize/references/observability-plus.md +109 -109
  516. package/skills/craft/vercel-optimize/references/playbooks/README.md +57 -57
  517. package/skills/craft/vercel-optimize/references/playbooks/ai-application.md +32 -32
  518. package/skills/craft/vercel-optimize/references/playbooks/api-service.md +30 -30
  519. package/skills/craft/vercel-optimize/references/playbooks/content-site.md +30 -30
  520. package/skills/craft/vercel-optimize/references/playbooks/ecommerce.md +30 -30
  521. package/skills/craft/vercel-optimize/references/playbooks/marketing.md +30 -30
  522. package/skills/craft/vercel-optimize/references/playbooks/saas.md +31 -31
  523. package/skills/craft/vercel-optimize/references/playbooks/sveltekit.md +75 -75
  524. package/skills/craft/vercel-optimize/references/recommendations.md +214 -214
  525. package/skills/craft/vercel-optimize/references/scanner-patterns.md +266 -266
  526. package/skills/craft/vercel-optimize/references/scoring.md +208 -208
  527. package/skills/craft/vercel-optimize/references/support-topics/README.md +50 -50
  528. package/skills/craft/vercel-optimize/references/support-topics/astro-edge-middleware-scope.md +30 -30
  529. package/skills/craft/vercel-optimize/references/support-topics/astro-output-mode-and-isr.md +31 -31
  530. package/skills/craft/vercel-optimize/references/support-topics/auth-preserving-parallelization.md +30 -30
  531. package/skills/craft/vercel-optimize/references/support-topics/bot-protection-product-guardrails.md +32 -32
  532. package/skills/craft/vercel-optimize/references/support-topics/build-minutes-monorepo-fanout.md +32 -32
  533. package/skills/craft/vercel-optimize/references/support-topics/cache-components-static-shell-boundaries.md +31 -31
  534. package/skills/craft/vercel-optimize/references/support-topics/cache-components-suspense-dedupe-pitfall.md +32 -32
  535. package/skills/craft/vercel-optimize/references/support-topics/cdn-cache-auth-safety.md +31 -31
  536. package/skills/craft/vercel-optimize/references/support-topics/cold-start-initialization-bundle.md +31 -31
  537. package/skills/craft/vercel-optimize/references/support-topics/core-web-vitals-client-bottlenecks.md +33 -33
  538. package/skills/craft/vercel-optimize/references/support-topics/database-egress-pooling-region.md +32 -32
  539. package/skills/craft/vercel-optimize/references/support-topics/dynamic-rendering-traps.md +31 -31
  540. package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path-platform.md +31 -31
  541. package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path.md +31 -31
  542. package/skills/craft/vercel-optimize/references/support-topics/fast-data-transfer-payloads.md +26 -26
  543. package/skills/craft/vercel-optimize/references/support-topics/fluid-compute-caveats.md +26 -26
  544. package/skills/craft/vercel-optimize/references/support-topics/function-duration-io-and-after.md +31 -31
  545. package/skills/craft/vercel-optimize/references/support-topics/function-invocation-reduction.md +31 -31
  546. package/skills/craft/vercel-optimize/references/support-topics/function-region-misconfiguration-ttfb.md +31 -31
  547. package/skills/craft/vercel-optimize/references/support-topics/image-optimization-cost-control.md +31 -31
  548. package/skills/craft/vercel-optimize/references/support-topics/isr-revalidation-static-generation.md +31 -31
  549. package/skills/craft/vercel-optimize/references/support-topics/middleware-proxy-edge-cost.md +30 -30
  550. package/skills/craft/vercel-optimize/references/support-topics/next-fetch-revalidate-floor.md +30 -30
  551. package/skills/craft/vercel-optimize/references/support-topics/next-font-cls-self-hosting.md +31 -31
  552. package/skills/craft/vercel-optimize/references/support-topics/next-heavy-ui-lazy-load-boundaries.md +28 -28
  553. package/skills/craft/vercel-optimize/references/support-topics/next-image-lcp-preload-sizes.md +31 -31
  554. package/skills/craft/vercel-optimize/references/support-topics/next-route-handler-get-cache-defaults.md +30 -30
  555. package/skills/craft/vercel-optimize/references/support-topics/next-script-third-party-strategy.md +31 -31
  556. package/skills/craft/vercel-optimize/references/support-topics/nextjs-version-cache-semantics.md +31 -31
  557. package/skills/craft/vercel-optimize/references/support-topics/not-found-catchall-request-waste.md +33 -33
  558. package/skills/craft/vercel-optimize/references/support-topics/nuxt-route-rules-cache-isr.md +31 -31
  559. package/skills/craft/vercel-optimize/references/support-topics/observability-events-cost-attribution.md +27 -27
  560. package/skills/craft/vercel-optimize/references/support-topics/post-response-work-waituntil.md +26 -26
  561. package/skills/craft/vercel-optimize/references/support-topics/route-error-durable-offload.md +33 -33
  562. package/skills/craft/vercel-optimize/references/support-topics/route-error-runtime-limits.md +31 -31
  563. package/skills/craft/vercel-optimize/references/support-topics/runtime-cache-reusable-data.md +30 -30
  564. package/skills/craft/vercel-optimize/references/support-topics/sveltekit-isr-prerender-safety.md +31 -31
  565. package/skills/craft/vercel-optimize/references/support-topics/sveltekit-split-cold-start-tradeoff.md +30 -30
  566. package/skills/craft/vercel-optimize/references/support-topics/usage-spike-triage.md +31 -31
  567. package/skills/craft/vercel-optimize/references/support-topics/use-cache-date-stamp-isr-write-amplifier.md +31 -31
  568. package/skills/craft/vercel-optimize/references/support-topics/use-cache-remote-shared-origin-data.md +30 -30
  569. package/skills/craft/vercel-optimize/references/support-topics/workflow-resumable-stream-routes.md +32 -32
  570. package/skills/craft/vercel-optimize/references/verification.md +102 -102
  571. package/skills/craft/vercel-optimize/references/voice.md +76 -76
  572. package/skills/craft/vercel-optimize/scripts/budget-summary.mjs +58 -58
  573. package/skills/craft/vercel-optimize/scripts/build-docs.mjs +76 -76
  574. package/skills/craft/vercel-optimize/scripts/check-citations.mjs +91 -91
  575. package/skills/craft/vercel-optimize/scripts/check-docs-fresh.mjs +100 -100
  576. package/skills/craft/vercel-optimize/scripts/collect-signals.mjs +638 -638
  577. package/skills/craft/vercel-optimize/scripts/collect-sub-agent-outputs.mjs +306 -306
  578. package/skills/craft/vercel-optimize/scripts/deep-dive.mjs +358 -358
  579. package/skills/craft/vercel-optimize/scripts/gate-investigations.mjs +178 -178
  580. package/skills/craft/vercel-optimize/scripts/merge-signals.mjs +203 -203
  581. package/skills/craft/vercel-optimize/scripts/prepare-investigation-brief.mjs +249 -249
  582. package/skills/craft/vercel-optimize/scripts/reconcile-candidates.mjs +69 -69
  583. package/skills/craft/vercel-optimize/scripts/render-report.mjs +462 -462
  584. package/skills/craft/vercel-optimize/scripts/scan-codebase.mjs +361 -361
  585. package/skills/craft/vercel-optimize/scripts/verify-and-regen.mjs +379 -379
  586. package/skills/craft/vercel-optimize/scripts/verify-finding.mjs +21 -21
  587. package/skills/craft/web-design-guidelines/LICENSE +21 -21
  588. package/skills/craft/web-design-guidelines/SKILL.md +43 -43
  589. package/skills/craft/zero-to-live/LICENSE +21 -21
  590. package/skills/craft/zero-to-live/SKILL.md +422 -422
  591. package/skills/creative/creative-3d-modeling/LICENSE +21 -21
  592. package/skills/creative/creative-3d-modeling/SKILL.md +70 -70
  593. package/skills/creative/creative-architecture/LICENSE +21 -21
  594. package/skills/creative/creative-architecture/SKILL.md +94 -94
  595. package/skills/creative/creative-design-principles/LICENSE +21 -21
  596. package/skills/creative/creative-design-principles/SKILL.md +95 -95
  597. package/skills/creative/creative-fashion-advanced/LICENSE +21 -21
  598. package/skills/creative/creative-fashion-advanced/SKILL.md +68 -68
  599. package/skills/creative/creative-fashion-design/LICENSE +21 -21
  600. package/skills/creative/creative-fashion-design/SKILL.md +66 -66
  601. package/skills/creative/creative-game-design/LICENSE +21 -21
  602. package/skills/creative/creative-game-design/SKILL.md +77 -77
  603. package/skills/creative/creative-industrial-design/LICENSE +21 -21
  604. package/skills/creative/creative-industrial-design/SKILL.md +57 -57
  605. package/skills/creative/creative-interior-design/LICENSE +21 -21
  606. package/skills/creative/creative-interior-design/SKILL.md +59 -59
  607. package/skills/creative/creative-music-theory/LICENSE +21 -21
  608. package/skills/creative/creative-music-theory/SKILL.md +98 -98
  609. package/skills/creative/creative-photography/LICENSE +21 -21
  610. package/skills/creative/creative-photography/SKILL.md +87 -87
  611. package/skills/creative/creative-textile-science/LICENSE +21 -21
  612. package/skills/creative/creative-textile-science/SKILL.md +67 -67
  613. package/skills/creative/creative-ux/LICENSE +21 -21
  614. package/skills/creative/creative-ux/SKILL.md +81 -81
  615. package/skills/creative/creative-video/LICENSE +21 -21
  616. package/skills/creative/creative-video/SKILL.md +84 -84
  617. package/skills/creative/creative-writing-craft/LICENSE +21 -21
  618. package/skills/creative/creative-writing-craft/SKILL.md +91 -91
  619. package/skills/diagram-maker/SKILL.md +56 -56
  620. package/skills/diagram-maker/references/excalidraw-patterns.md +85 -85
  621. package/skills/diagram-maker/references/svg-template.md +112 -112
  622. package/skills/discord/SKILL.md +140 -140
  623. package/skills/education/edu-adult-learning/LICENSE +21 -21
  624. package/skills/education/edu-adult-learning/SKILL.md +81 -81
  625. package/skills/education/edu-africa-multilingual/LICENSE +21 -21
  626. package/skills/education/edu-africa-multilingual/SKILL.md +55 -55
  627. package/skills/education/edu-arabic/LICENSE +21 -21
  628. package/skills/education/edu-arabic/SKILL.md +60 -60
  629. package/skills/education/edu-australia-nz/LICENSE +21 -21
  630. package/skills/education/edu-australia-nz/SKILL.md +48 -48
  631. package/skills/education/edu-china-mandarin/LICENSE +21 -21
  632. package/skills/education/edu-china-mandarin/SKILL.md +58 -58
  633. package/skills/education/edu-critical-thinking/LICENSE +21 -21
  634. package/skills/education/edu-critical-thinking/SKILL.md +86 -86
  635. package/skills/education/edu-curriculum/LICENSE +21 -21
  636. package/skills/education/edu-curriculum/SKILL.md +87 -87
  637. package/skills/education/edu-ed-tech/LICENSE +21 -21
  638. package/skills/education/edu-ed-tech/SKILL.md +73 -73
  639. package/skills/education/edu-france/LICENSE +21 -21
  640. package/skills/education/edu-france/SKILL.md +42 -42
  641. package/skills/education/edu-germany/LICENSE +21 -21
  642. package/skills/education/edu-germany/SKILL.md +46 -46
  643. package/skills/education/edu-india-competitive/LICENSE +21 -21
  644. package/skills/education/edu-india-competitive/SKILL.md +159 -159
  645. package/skills/education/edu-india-east/LICENSE +21 -21
  646. package/skills/education/edu-india-east/SKILL.md +60 -60
  647. package/skills/education/edu-india-hindi/LICENSE +21 -21
  648. package/skills/education/edu-india-hindi/SKILL.md +107 -107
  649. package/skills/education/edu-india-south/LICENSE +21 -21
  650. package/skills/education/edu-india-south/SKILL.md +64 -64
  651. package/skills/education/edu-india-west/LICENSE +21 -21
  652. package/skills/education/edu-india-west/SKILL.md +68 -68
  653. package/skills/education/edu-indonesia-malay/LICENSE +21 -21
  654. package/skills/education/edu-indonesia-malay/SKILL.md +57 -57
  655. package/skills/education/edu-international-ib/LICENSE +21 -21
  656. package/skills/education/edu-international-ib/SKILL.md +61 -61
  657. package/skills/education/edu-japan/LICENSE +21 -21
  658. package/skills/education/edu-japan/SKILL.md +48 -48
  659. package/skills/education/edu-korea/LICENSE +21 -21
  660. package/skills/education/edu-korea/SKILL.md +48 -48
  661. package/skills/education/edu-learning-science/LICENSE +21 -21
  662. package/skills/education/edu-learning-science/SKILL.md +76 -76
  663. package/skills/education/edu-portuguese-brazil/LICENSE +21 -21
  664. package/skills/education/edu-portuguese-brazil/SKILL.md +51 -51
  665. package/skills/education/edu-russia/LICENSE +21 -21
  666. package/skills/education/edu-russia/SKILL.md +50 -50
  667. package/skills/education/edu-spain-latam/LICENSE +21 -21
  668. package/skills/education/edu-spain-latam/SKILL.md +55 -55
  669. package/skills/education/edu-special/LICENSE +21 -21
  670. package/skills/education/edu-special/SKILL.md +76 -76
  671. package/skills/education/edu-thailand/LICENSE +21 -21
  672. package/skills/education/edu-thailand/SKILL.md +55 -55
  673. package/skills/education/edu-turkey/LICENSE +21 -21
  674. package/skills/education/edu-turkey/SKILL.md +58 -58
  675. package/skills/education/edu-uk-gcse-alevel/LICENSE +21 -21
  676. package/skills/education/edu-uk-gcse-alevel/SKILL.md +51 -51
  677. package/skills/education/edu-usa-graduate/LICENSE +21 -21
  678. package/skills/education/edu-usa-graduate/SKILL.md +57 -57
  679. package/skills/education/edu-usa-sat-act/LICENSE +21 -21
  680. package/skills/education/edu-usa-sat-act/SKILL.md +55 -55
  681. package/skills/education/edu-vietnam/LICENSE +21 -21
  682. package/skills/education/edu-vietnam/SKILL.md +53 -53
  683. package/skills/eightctl/SKILL.md +54 -54
  684. package/skills/engineering/eng-aerospace/LICENSE +21 -21
  685. package/skills/engineering/eng-aerospace/SKILL.md +117 -117
  686. package/skills/engineering/eng-chemical/LICENSE +21 -21
  687. package/skills/engineering/eng-chemical/SKILL.md +63 -63
  688. package/skills/engineering/eng-civil/LICENSE +21 -21
  689. package/skills/engineering/eng-civil/SKILL.md +223 -223
  690. package/skills/engineering/eng-control-systems/LICENSE +21 -21
  691. package/skills/engineering/eng-control-systems/SKILL.md +158 -158
  692. package/skills/engineering/eng-cryogenics/LICENSE +21 -21
  693. package/skills/engineering/eng-cryogenics/SKILL.md +151 -151
  694. package/skills/engineering/eng-electrical/LICENSE +21 -21
  695. package/skills/engineering/eng-electrical/SKILL.md +70 -70
  696. package/skills/engineering/eng-electronics-embedded/LICENSE +21 -21
  697. package/skills/engineering/eng-electronics-embedded/SKILL.md +89 -89
  698. package/skills/engineering/eng-environmental/LICENSE +21 -21
  699. package/skills/engineering/eng-environmental/SKILL.md +66 -66
  700. package/skills/engineering/eng-manufacturing/LICENSE +21 -21
  701. package/skills/engineering/eng-manufacturing/SKILL.md +78 -78
  702. package/skills/engineering/eng-mechanical/LICENSE +21 -21
  703. package/skills/engineering/eng-mechanical/SKILL.md +66 -66
  704. package/skills/engineering/eng-project/LICENSE +21 -21
  705. package/skills/engineering/eng-project/SKILL.md +72 -72
  706. package/skills/engineering/eng-propulsion/LICENSE +21 -21
  707. package/skills/engineering/eng-propulsion/SKILL.md +133 -133
  708. package/skills/engineering/eng-robotics/LICENSE +21 -21
  709. package/skills/engineering/eng-robotics/SKILL.md +92 -92
  710. package/skills/engineering/eng-systems/LICENSE +21 -21
  711. package/skills/engineering/eng-systems/SKILL.md +81 -81
  712. package/skills/environment/env-biodiversity/LICENSE +21 -21
  713. package/skills/environment/env-biodiversity/SKILL.md +66 -66
  714. package/skills/environment/env-circular-economy/LICENSE +21 -21
  715. package/skills/environment/env-circular-economy/SKILL.md +71 -71
  716. package/skills/environment/env-climate-action/LICENSE +21 -21
  717. package/skills/environment/env-climate-action/SKILL.md +55 -55
  718. package/skills/environment/env-energy/LICENSE +21 -21
  719. package/skills/environment/env-energy/SKILL.md +83 -83
  720. package/skills/environment/env-sustainability-biz/LICENSE +21 -21
  721. package/skills/environment/env-sustainability-biz/SKILL.md +65 -65
  722. package/skills/environment/env-water/LICENSE +21 -21
  723. package/skills/environment/env-water/SKILL.md +67 -67
  724. package/skills/finance/finance-accounting/LICENSE +21 -21
  725. package/skills/finance/finance-accounting/SKILL.md +239 -239
  726. package/skills/finance/finance-banking/LICENSE +21 -21
  727. package/skills/finance/finance-banking/SKILL.md +54 -54
  728. package/skills/finance/finance-corporate/LICENSE +21 -21
  729. package/skills/finance/finance-corporate/SKILL.md +105 -105
  730. package/skills/finance/finance-crypto/LICENSE +21 -21
  731. package/skills/finance/finance-crypto/SKILL.md +94 -94
  732. package/skills/finance/finance-debt-management/LICENSE +21 -21
  733. package/skills/finance/finance-debt-management/SKILL.md +87 -87
  734. package/skills/finance/finance-insurance/LICENSE +21 -21
  735. package/skills/finance/finance-insurance/SKILL.md +91 -91
  736. package/skills/finance/finance-investing/LICENSE +21 -21
  737. package/skills/finance/finance-investing/SKILL.md +269 -269
  738. package/skills/finance/finance-options-derivatives/LICENSE +21 -21
  739. package/skills/finance/finance-options-derivatives/SKILL.md +68 -68
  740. package/skills/finance/finance-personal/LICENSE +21 -21
  741. package/skills/finance/finance-personal/SKILL.md +268 -268
  742. package/skills/finance/finance-real-estate/LICENSE +21 -21
  743. package/skills/finance/finance-real-estate/SKILL.md +110 -110
  744. package/skills/finance/finance-startup/LICENSE +21 -21
  745. package/skills/finance/finance-startup/SKILL.md +253 -253
  746. package/skills/finance/finance-tax-planning/LICENSE +21 -21
  747. package/skills/finance/finance-tax-planning/SKILL.md +89 -89
  748. package/skills/finance/finance-trading/LICENSE +21 -21
  749. package/skills/finance/finance-trading/SKILL.md +112 -112
  750. package/skills/gemini/SKILL.md +51 -51
  751. package/skills/gh-issues/SKILL.md +216 -216
  752. package/skills/gifgrep/SKILL.md +89 -89
  753. package/skills/github/SKILL.md +87 -87
  754. package/skills/gog/SKILL.md +120 -120
  755. package/skills/goplaces/SKILL.md +56 -56
  756. package/skills/health/health-aging/LICENSE +21 -21
  757. package/skills/health/health-aging/SKILL.md +82 -82
  758. package/skills/health/health-chronic/LICENSE +21 -21
  759. package/skills/health/health-chronic/SKILL.md +202 -202
  760. package/skills/health/health-dental/LICENSE +21 -21
  761. package/skills/health/health-dental/SKILL.md +41 -41
  762. package/skills/health/health-eye-care/LICENSE +21 -21
  763. package/skills/health/health-eye-care/SKILL.md +56 -56
  764. package/skills/health/health-first-aid/LICENSE +21 -21
  765. package/skills/health/health-first-aid/SKILL.md +201 -201
  766. package/skills/health/health-fitness/LICENSE +21 -21
  767. package/skills/health/health-fitness/SKILL.md +111 -111
  768. package/skills/health/health-general/LICENSE +21 -21
  769. package/skills/health/health-general/SKILL.md +277 -277
  770. package/skills/health/health-mens/LICENSE +21 -21
  771. package/skills/health/health-mens/SKILL.md +53 -53
  772. package/skills/health/health-mental/LICENSE +21 -21
  773. package/skills/health/health-mental/SKILL.md +221 -221
  774. package/skills/health/health-naturopathy-ayurveda/LICENSE +21 -21
  775. package/skills/health/health-naturopathy-ayurveda/SKILL.md +60 -60
  776. package/skills/health/health-nutrition/LICENSE +21 -21
  777. package/skills/health/health-nutrition/SKILL.md +262 -262
  778. package/skills/health/health-pediatric/LICENSE +21 -21
  779. package/skills/health/health-pediatric/SKILL.md +94 -94
  780. package/skills/health/health-pharmacology/LICENSE +21 -21
  781. package/skills/health/health-pharmacology/SKILL.md +87 -87
  782. package/skills/health/health-pregnancy/LICENSE +21 -21
  783. package/skills/health/health-pregnancy/SKILL.md +71 -71
  784. package/skills/health/health-skin/LICENSE +21 -21
  785. package/skills/health/health-skin/SKILL.md +71 -71
  786. package/skills/health/health-sleep/LICENSE +21 -21
  787. package/skills/health/health-sleep/SKILL.md +81 -81
  788. package/skills/health/health-womens/LICENSE +21 -21
  789. package/skills/health/health-womens/SKILL.md +72 -72
  790. package/skills/health/health-yoga-wellness/LICENSE +21 -21
  791. package/skills/health/health-yoga-wellness/SKILL.md +58 -58
  792. package/skills/healthcare-systems/health-sys-global/LICENSE +21 -21
  793. package/skills/healthcare-systems/health-sys-global/SKILL.md +69 -69
  794. package/skills/healthcare-systems/health-sys-management/LICENSE +21 -21
  795. package/skills/healthcare-systems/health-sys-management/SKILL.md +71 -71
  796. package/skills/healthcare-systems/health-sys-navigation/LICENSE +21 -21
  797. package/skills/healthcare-systems/health-sys-navigation/SKILL.md +60 -60
  798. package/skills/healthcare-systems/health-sys-public/LICENSE +21 -21
  799. package/skills/healthcare-systems/health-sys-public/SKILL.md +71 -71
  800. package/skills/healthcheck/SKILL.md +109 -109
  801. package/skills/himalaya/SKILL.md +84 -84
  802. package/skills/himalaya/references/configuration.md +184 -184
  803. package/skills/himalaya/references/message-composition.md +199 -199
  804. package/skills/humanities/humanities-history-world/LICENSE +21 -21
  805. package/skills/humanities/humanities-history-world/SKILL.md +59 -59
  806. package/skills/humanities/humanities-indian-classical/LICENSE +21 -21
  807. package/skills/humanities/humanities-indian-classical/SKILL.md +104 -104
  808. package/skills/humanities/humanities-philosophy/LICENSE +21 -21
  809. package/skills/humanities/humanities-philosophy/SKILL.md +105 -105
  810. package/skills/humanities/humanities-world-religions/LICENSE +21 -21
  811. package/skills/humanities/humanities-world-religions/SKILL.md +67 -67
  812. package/skills/impeccable/SKILL.md +185 -185
  813. package/skills/imsg/SKILL.md +126 -126
  814. package/skills/industry/industry-construction/LICENSE +21 -21
  815. package/skills/industry/industry-construction/SKILL.md +81 -81
  816. package/skills/industry/industry-education-sector/LICENSE +21 -21
  817. package/skills/industry/industry-education-sector/SKILL.md +49 -49
  818. package/skills/industry/industry-fashion/LICENSE +21 -21
  819. package/skills/industry/industry-fashion/SKILL.md +82 -82
  820. package/skills/industry/industry-food/LICENSE +21 -21
  821. package/skills/industry/industry-food/SKILL.md +79 -79
  822. package/skills/industry/industry-government/LICENSE +21 -21
  823. package/skills/industry/industry-government/SKILL.md +80 -80
  824. package/skills/industry/industry-hospitality/LICENSE +21 -21
  825. package/skills/industry/industry-hospitality/SKILL.md +73 -73
  826. package/skills/industry/industry-insurance-sector/LICENSE +21 -21
  827. package/skills/industry/industry-insurance-sector/SKILL.md +57 -57
  828. package/skills/industry/industry-logistics/LICENSE +21 -21
  829. package/skills/industry/industry-logistics/SKILL.md +80 -80
  830. package/skills/industry/industry-media/LICENSE +21 -21
  831. package/skills/industry/industry-media/SKILL.md +66 -66
  832. package/skills/industry/industry-nonprofit/LICENSE +21 -21
  833. package/skills/industry/industry-nonprofit/SKILL.md +77 -77
  834. package/skills/industry/industry-pharma/LICENSE +21 -21
  835. package/skills/industry/industry-pharma/SKILL.md +69 -69
  836. package/skills/industry/industry-real-estate/LICENSE +21 -21
  837. package/skills/industry/industry-real-estate/SKILL.md +61 -61
  838. package/skills/industry/industry-sports/LICENSE +21 -21
  839. package/skills/industry/industry-sports/SKILL.md +71 -71
  840. package/skills/industry/industry-tech-startup/LICENSE +21 -21
  841. package/skills/industry/industry-tech-startup/SKILL.md +82 -82
  842. package/skills/internal-comms/LICENSE +21 -21
  843. package/skills/internal-comms/SKILL.md +38 -38
  844. package/skills/internal-comms/examples/3p-updates.md +49 -49
  845. package/skills/internal-comms/examples/company-newsletter.md +76 -76
  846. package/skills/internal-comms/examples/faq-answers.md +35 -35
  847. package/skills/internal-comms/examples/general-comms.md +19 -19
  848. package/skills/legal/legal-business/LICENSE +21 -21
  849. package/skills/legal/legal-business/SKILL.md +227 -227
  850. package/skills/legal/legal-consumer/LICENSE +21 -21
  851. package/skills/legal/legal-consumer/SKILL.md +155 -155
  852. package/skills/legal/legal-contracts/LICENSE +21 -21
  853. package/skills/legal/legal-contracts/SKILL.md +268 -268
  854. package/skills/legal/legal-corporate-governance/LICENSE +21 -21
  855. package/skills/legal/legal-corporate-governance/SKILL.md +53 -53
  856. package/skills/legal/legal-employment/LICENSE +21 -21
  857. package/skills/legal/legal-employment/SKILL.md +291 -291
  858. package/skills/legal/legal-immigration/LICENSE +21 -21
  859. package/skills/legal/legal-immigration/SKILL.md +146 -146
  860. package/skills/legal/legal-international/LICENSE +21 -21
  861. package/skills/legal/legal-international/SKILL.md +51 -51
  862. package/skills/legal/legal-ip/LICENSE +21 -21
  863. package/skills/legal/legal-ip/SKILL.md +264 -264
  864. package/skills/legal/legal-privacy/LICENSE +21 -21
  865. package/skills/legal/legal-privacy/SKILL.md +161 -161
  866. package/skills/legal/legal-real-estate/LICENSE +21 -21
  867. package/skills/legal/legal-real-estate/SKILL.md +142 -142
  868. package/skills/legal/legal-startup/LICENSE +21 -21
  869. package/skills/legal/legal-startup/SKILL.md +182 -182
  870. package/skills/legal/legal-tax/LICENSE +21 -21
  871. package/skills/legal/legal-tax/SKILL.md +156 -156
  872. package/skills/mcp-builder/LICENSE +21 -21
  873. package/skills/mcp-builder/SKILL.md +257 -257
  874. package/skills/mcp-builder/reference/evaluation.md +630 -630
  875. package/skills/mcp-builder/reference/mcp_best_practices.md +269 -269
  876. package/skills/mcp-builder/reference/node_mcp_server.md +980 -980
  877. package/skills/mcp-builder/reference/python_mcp_server.md +737 -737
  878. package/skills/mcp-builder/scripts/connections.py +151 -151
  879. package/skills/mcp-builder/scripts/evaluation.py +373 -373
  880. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
  881. package/skills/mcp-builder/scripts/requirements.txt +2 -2
  882. package/skills/mcporter/SKILL.md +65 -65
  883. package/skills/meme-maker/SKILL.md +46 -46
  884. package/skills/meme-maker/references/templates.json +358 -358
  885. package/skills/meme-maker/scripts/meme.mjs +398 -398
  886. package/skills/mental-health/mental-health-cbt/LICENSE +21 -21
  887. package/skills/mental-health/mental-health-cbt/SKILL.md +254 -254
  888. package/skills/mental-health/psych-addiction/LICENSE +21 -21
  889. package/skills/mental-health/psych-addiction/SKILL.md +79 -79
  890. package/skills/mental-health/psych-behavioral-econ/LICENSE +21 -21
  891. package/skills/mental-health/psych-behavioral-econ/SKILL.md +84 -84
  892. package/skills/mental-health/psych-child/LICENSE +21 -21
  893. package/skills/mental-health/psych-child/SKILL.md +84 -84
  894. package/skills/mental-health/psych-grief/LICENSE +21 -21
  895. package/skills/mental-health/psych-grief/SKILL.md +85 -85
  896. package/skills/mental-health/psych-mindfulness/LICENSE +21 -21
  897. package/skills/mental-health/psych-mindfulness/SKILL.md +71 -71
  898. package/skills/mental-health/psych-org/LICENSE +21 -21
  899. package/skills/mental-health/psych-org/SKILL.md +115 -115
  900. package/skills/mental-health/psych-positive/LICENSE +21 -21
  901. package/skills/mental-health/psych-positive/SKILL.md +86 -86
  902. package/skills/mental-health/psych-relationships/LICENSE +21 -21
  903. package/skills/mental-health/psych-relationships/SKILL.md +100 -100
  904. package/skills/mental-health/psych-trauma/LICENSE +21 -21
  905. package/skills/mental-health/psych-trauma/SKILL.md +109 -109
  906. package/skills/model-usage/SKILL.md +75 -75
  907. package/skills/model-usage/references/codexbar-cli.md +33 -33
  908. package/skills/model-usage/scripts/model_usage.py +319 -319
  909. package/skills/model-usage/scripts/test_model_usage.py +40 -40
  910. package/skills/nano-pdf/SKILL.md +42 -42
  911. package/skills/node-connect/SKILL.md +147 -147
  912. package/skills/node-inspect-debugger/SKILL.md +88 -88
  913. package/skills/notion/SKILL.md +154 -154
  914. package/skills/obsidian/SKILL.md +123 -123
  915. package/skills/openai-whisper/SKILL.md +42 -42
  916. package/skills/openai-whisper-api/SKILL.md +75 -75
  917. package/skills/openai-whisper-api/scripts/transcribe.sh +154 -154
  918. package/skills/openhue/SKILL.md +116 -116
  919. package/skills/oracle/SKILL.md +130 -130
  920. package/skills/ordercli/SKILL.md +82 -82
  921. package/skills/peekaboo/SKILL.md +217 -217
  922. package/skills/pyproject.toml +10 -10
  923. package/skills/python-debugpy/SKILL.md +76 -76
  924. package/skills/sag/SKILL.md +91 -91
  925. package/skills/science/sci-astronomy/LICENSE +21 -21
  926. package/skills/science/sci-astronomy/SKILL.md +80 -80
  927. package/skills/science/sci-biology/LICENSE +21 -21
  928. package/skills/science/sci-biology/SKILL.md +74 -74
  929. package/skills/science/sci-chemistry/LICENSE +21 -21
  930. package/skills/science/sci-chemistry/SKILL.md +89 -89
  931. package/skills/science/sci-climate/LICENSE +21 -21
  932. package/skills/science/sci-climate/SKILL.md +72 -72
  933. package/skills/science/sci-data-analysis/LICENSE +21 -21
  934. package/skills/science/sci-data-analysis/SKILL.md +87 -87
  935. package/skills/science/sci-environmental-science/LICENSE +21 -21
  936. package/skills/science/sci-environmental-science/SKILL.md +69 -69
  937. package/skills/science/sci-geology/LICENSE +21 -21
  938. package/skills/science/sci-geology/SKILL.md +56 -56
  939. package/skills/science/sci-method/LICENSE +21 -21
  940. package/skills/science/sci-method/SKILL.md +77 -77
  941. package/skills/science/sci-neuroscience/LICENSE +21 -21
  942. package/skills/science/sci-neuroscience/SKILL.md +79 -79
  943. package/skills/science/sci-physics/LICENSE +21 -21
  944. package/skills/science/sci-physics/SKILL.md +78 -78
  945. package/skills/science/sci-research-methods/LICENSE +21 -21
  946. package/skills/science/sci-research-methods/SKILL.md +83 -83
  947. package/skills/science/sci-statistics/LICENSE +21 -21
  948. package/skills/science/sci-statistics/SKILL.md +249 -249
  949. package/skills/session-logs/SKILL.md +155 -155
  950. package/skills/sherpa-onnx-tts/SKILL.md +113 -113
  951. package/skills/skill-creator/SKILL.md +81 -81
  952. package/skills/skill-creator/license.txt +202 -202
  953. package/skills/skill-creator/scripts/init_skill.py +378 -378
  954. package/skills/skill-creator/scripts/package_skill.py +144 -144
  955. package/skills/skill-creator/scripts/quick_validate.py +169 -169
  956. package/skills/skill-creator/scripts/test_init_skill.py +51 -51
  957. package/skills/skill-creator/scripts/test_package_skill.py +199 -199
  958. package/skills/skill-creator/scripts/test_quick_validate.py +116 -116
  959. package/skills/slack/SKILL.md +82 -82
  960. package/skills/slack-gif-creator/LICENSE +21 -21
  961. package/skills/slack-gif-creator/SKILL.md +293 -293
  962. package/skills/slack-gif-creator/requirements.txt +3 -3
  963. package/skills/social-sciences/social-anthropology/LICENSE +21 -21
  964. package/skills/social-sciences/social-anthropology/SKILL.md +62 -62
  965. package/skills/social-sciences/social-economics/LICENSE +21 -21
  966. package/skills/social-sciences/social-economics/SKILL.md +88 -88
  967. package/skills/social-sciences/social-geography/LICENSE +21 -21
  968. package/skills/social-sciences/social-geography/SKILL.md +61 -61
  969. package/skills/social-sciences/social-international-dev/LICENSE +21 -21
  970. package/skills/social-sciences/social-international-dev/SKILL.md +76 -76
  971. package/skills/social-sciences/social-political-science/LICENSE +21 -21
  972. package/skills/social-sciences/social-political-science/SKILL.md +70 -70
  973. package/skills/social-sciences/social-public-policy/LICENSE +21 -21
  974. package/skills/social-sciences/social-public-policy/SKILL.md +73 -73
  975. package/skills/social-sciences/social-sociology/LICENSE +21 -21
  976. package/skills/social-sciences/social-sociology/SKILL.md +78 -78
  977. package/skills/songsee/SKILL.md +53 -53
  978. package/skills/sonoscli/SKILL.md +69 -69
  979. package/skills/spike/SKILL.md +55 -55
  980. package/skills/spotify-player/SKILL.md +68 -68
  981. package/skills/summarize/SKILL.md +90 -90
  982. package/skills/taskflow/SKILL.md +153 -153
  983. package/skills/taskflow/examples/inbox-triage.lobster +33 -33
  984. package/skills/taskflow/examples/pr-intake.lobster +32 -32
  985. package/skills/taskflow-inbox-triage/SKILL.md +123 -123
  986. package/skills/technical/ai-ethics/LICENSE +21 -21
  987. package/skills/technical/ai-ethics/SKILL.md +92 -92
  988. package/skills/technical/ai-product-builder/LICENSE +21 -21
  989. package/skills/technical/ai-product-builder/SKILL.md +180 -180
  990. package/skills/technical/analytics-setup/LICENSE +21 -21
  991. package/skills/technical/analytics-setup/SKILL.md +125 -125
  992. package/skills/technical/api-builder/LICENSE +21 -21
  993. package/skills/technical/api-builder/SKILL.md +202 -202
  994. package/skills/technical/architecture-decisions/LICENSE +21 -21
  995. package/skills/technical/architecture-decisions/SKILL.md +120 -120
  996. package/skills/technical/auth-security/LICENSE +21 -21
  997. package/skills/technical/auth-security/SKILL.md +209 -209
  998. package/skills/technical/blockchain-web3/LICENSE +21 -21
  999. package/skills/technical/blockchain-web3/SKILL.md +84 -84
  1000. package/skills/technical/cloud-architecture/LICENSE +21 -21
  1001. package/skills/technical/cloud-architecture/SKILL.md +85 -85
  1002. package/skills/technical/content-platform/LICENSE +21 -21
  1003. package/skills/technical/content-platform/SKILL.md +134 -134
  1004. package/skills/technical/cybersecurity-advanced/LICENSE +21 -21
  1005. package/skills/technical/cybersecurity-advanced/SKILL.md +99 -99
  1006. package/skills/technical/data-engineering/LICENSE +21 -21
  1007. package/skills/technical/data-engineering/SKILL.md +117 -117
  1008. package/skills/technical/database-design/LICENSE +21 -21
  1009. package/skills/technical/database-design/SKILL.md +185 -185
  1010. package/skills/technical/devops-cicd/LICENSE +21 -21
  1011. package/skills/technical/devops-cicd/SKILL.md +181 -181
  1012. package/skills/technical/ecommerce-builder/LICENSE +21 -21
  1013. package/skills/technical/ecommerce-builder/SKILL.md +123 -123
  1014. package/skills/technical/email-marketing/LICENSE +21 -21
  1015. package/skills/technical/email-marketing/SKILL.md +128 -128
  1016. package/skills/technical/fintech-builder/LICENSE +21 -21
  1017. package/skills/technical/fintech-builder/SKILL.md +141 -141
  1018. package/skills/technical/full-stack-web/LICENSE +21 -21
  1019. package/skills/technical/full-stack-web/SKILL.md +173 -173
  1020. package/skills/technical/gdpr-basics/LICENSE +21 -21
  1021. package/skills/technical/gdpr-basics/SKILL.md +145 -145
  1022. package/skills/technical/launch-playbook/LICENSE +21 -21
  1023. package/skills/technical/launch-playbook/SKILL.md +95 -95
  1024. package/skills/technical/marketing-copy/LICENSE +21 -21
  1025. package/skills/technical/marketing-copy/SKILL.md +126 -126
  1026. package/skills/technical/marketplace-builder/LICENSE +21 -21
  1027. package/skills/technical/marketplace-builder/SKILL.md +105 -105
  1028. package/skills/technical/mobile-pwa/LICENSE +21 -21
  1029. package/skills/technical/mobile-pwa/SKILL.md +191 -191
  1030. package/skills/technical/no-code-tools/LICENSE +21 -21
  1031. package/skills/technical/no-code-tools/SKILL.md +80 -80
  1032. package/skills/technical/open-source/LICENSE +21 -21
  1033. package/skills/technical/open-source/SKILL.md +71 -71
  1034. package/skills/technical/performance-optimization/LICENSE +21 -21
  1035. package/skills/technical/performance-optimization/SKILL.md +155 -155
  1036. package/skills/technical/pricing-design/LICENSE +21 -21
  1037. package/skills/technical/pricing-design/SKILL.md +87 -87
  1038. package/skills/technical/product-management/LICENSE +21 -21
  1039. package/skills/technical/product-management/SKILL.md +94 -94
  1040. package/skills/technical/saas-builder/LICENSE +21 -21
  1041. package/skills/technical/saas-builder/SKILL.md +138 -138
  1042. package/skills/technical/scope-estimation/LICENSE +21 -21
  1043. package/skills/technical/scope-estimation/SKILL.md +99 -99
  1044. package/skills/technical/secrets-management/LICENSE +21 -21
  1045. package/skills/technical/secrets-management/SKILL.md +135 -135
  1046. package/skills/technical/seo-technical/LICENSE +21 -21
  1047. package/skills/technical/seo-technical/SKILL.md +136 -136
  1048. package/skills/technical/technical-writing/LICENSE +21 -21
  1049. package/skills/technical/technical-writing/SKILL.md +149 -149
  1050. package/skills/technical/ux-research-tools/LICENSE +21 -21
  1051. package/skills/technical/ux-research-tools/SKILL.md +54 -54
  1052. package/skills/theme-factory/LICENSE +21 -21
  1053. package/skills/theme-factory/SKILL.md +65 -65
  1054. package/skills/theme-factory/themes/arctic-frost.md +19 -19
  1055. package/skills/theme-factory/themes/botanical-garden.md +19 -19
  1056. package/skills/theme-factory/themes/desert-rose.md +19 -19
  1057. package/skills/theme-factory/themes/forest-canopy.md +19 -19
  1058. package/skills/theme-factory/themes/golden-hour.md +19 -19
  1059. package/skills/theme-factory/themes/midnight-galaxy.md +19 -19
  1060. package/skills/theme-factory/themes/modern-minimalist.md +19 -19
  1061. package/skills/theme-factory/themes/ocean-depths.md +19 -19
  1062. package/skills/theme-factory/themes/sunset-boulevard.md +19 -19
  1063. package/skills/theme-factory/themes/tech-innovation.md +19 -19
  1064. package/skills/things-mac/SKILL.md +90 -90
  1065. package/skills/tmux/SKILL.md +95 -95
  1066. package/skills/tmux/scripts/find-sessions.sh +112 -112
  1067. package/skills/tmux/scripts/wait-for-text.sh +83 -83
  1068. package/skills/trades/trades-agriculture/LICENSE +21 -21
  1069. package/skills/trades/trades-agriculture/SKILL.md +80 -80
  1070. package/skills/trades/trades-automotive/LICENSE +21 -21
  1071. package/skills/trades/trades-automotive/SKILL.md +84 -84
  1072. package/skills/trades/trades-carpentry/LICENSE +21 -21
  1073. package/skills/trades/trades-carpentry/SKILL.md +71 -71
  1074. package/skills/trades/trades-cooking-pro/LICENSE +21 -21
  1075. package/skills/trades/trades-cooking-pro/SKILL.md +90 -90
  1076. package/skills/trades/trades-electrical/LICENSE +21 -21
  1077. package/skills/trades/trades-electrical/SKILL.md +146 -146
  1078. package/skills/trades/trades-hvac/LICENSE +21 -21
  1079. package/skills/trades/trades-hvac/SKILL.md +80 -80
  1080. package/skills/trades/trades-landscaping/LICENSE +21 -21
  1081. package/skills/trades/trades-landscaping/SKILL.md +60 -60
  1082. package/skills/trades/trades-metalworking/LICENSE +21 -21
  1083. package/skills/trades/trades-metalworking/SKILL.md +64 -64
  1084. package/skills/trades/trades-painting/LICENSE +21 -21
  1085. package/skills/trades/trades-painting/SKILL.md +70 -70
  1086. package/skills/trades/trades-plumbing/LICENSE +21 -21
  1087. package/skills/trades/trades-plumbing/SKILL.md +160 -160
  1088. package/skills/trades/trades-welding/LICENSE +21 -21
  1089. package/skills/trades/trades-welding/SKILL.md +82 -82
  1090. package/skills/trello/SKILL.md +112 -112
  1091. package/skills/uipm-ui-styling/SKILL.md +328 -328
  1092. package/skills/video-frames/SKILL.md +50 -50
  1093. package/skills/video-frames/scripts/frame.sh +81 -81
  1094. package/skills/voice-call/SKILL.md +49 -49
  1095. package/skills/wacli/SKILL.md +76 -76
  1096. package/skills/weather/SKILL.md +91 -91
  1097. package/skills/web-artifacts-builder/LICENSE +21 -21
  1098. package/skills/web-artifacts-builder/SKILL.md +82 -82
  1099. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +53 -53
  1100. package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -322
  1101. package/skills/xurl/SKILL.md +124 -124
  1102. package/skills/graphify/SKILL.md +0 -619
  1103. package/skills/graphify/__init__.py +0 -28
  1104. package/skills/graphify/__main__.py +0 -4582
  1105. package/skills/graphify/affected.py +0 -154
  1106. package/skills/graphify/always_on/agents-md.md +0 -12
  1107. package/skills/graphify/always_on/antigravity-rules.md +0 -14
  1108. package/skills/graphify/always_on/claude-md.md +0 -9
  1109. package/skills/graphify/always_on/gemini-md.md +0 -9
  1110. package/skills/graphify/always_on/kiro-steering.md +0 -5
  1111. package/skills/graphify/always_on/vscode-instructions.md +0 -17
  1112. package/skills/graphify/analyze.py +0 -724
  1113. package/skills/graphify/benchmark.py +0 -155
  1114. package/skills/graphify/build.py +0 -487
  1115. package/skills/graphify/cache.py +0 -417
  1116. package/skills/graphify/callflow_html.py +0 -2020
  1117. package/skills/graphify/cluster.py +0 -272
  1118. package/skills/graphify/command-kilo.md +0 -15
  1119. package/skills/graphify/dedup.py +0 -429
  1120. package/skills/graphify/detect.py +0 -1379
  1121. package/skills/graphify/diagnostics.py +0 -390
  1122. package/skills/graphify/export.py +0 -1408
  1123. package/skills/graphify/extract.py +0 -11570
  1124. package/skills/graphify/global_graph.py +0 -159
  1125. package/skills/graphify/google_workspace.py +0 -223
  1126. package/skills/graphify/hooks.py +0 -457
  1127. package/skills/graphify/ingest.py +0 -331
  1128. package/skills/graphify/llm.py +0 -1896
  1129. package/skills/graphify/manifest.py +0 -4
  1130. package/skills/graphify/mcp_ingest.py +0 -392
  1131. package/skills/graphify/multigraph_compat.py +0 -212
  1132. package/skills/graphify/pg_introspect.py +0 -142
  1133. package/skills/graphify/prs.py +0 -748
  1134. package/skills/graphify/querylog.py +0 -70
  1135. package/skills/graphify/report.py +0 -218
  1136. package/skills/graphify/scip_ingest.py +0 -363
  1137. package/skills/graphify/security.py +0 -336
  1138. package/skills/graphify/semantic_cleanup.py +0 -319
  1139. package/skills/graphify/serve.py +0 -1309
  1140. package/skills/graphify/skill-aider.md +0 -1246
  1141. package/skills/graphify/skill-amp.md +0 -613
  1142. package/skills/graphify/skill-claw.md +0 -616
  1143. package/skills/graphify/skill-codex.md +0 -613
  1144. package/skills/graphify/skill-copilot.md +0 -616
  1145. package/skills/graphify/skill-devin.md +0 -1372
  1146. package/skills/graphify/skill-droid.md +0 -613
  1147. package/skills/graphify/skill-kilo.md +0 -625
  1148. package/skills/graphify/skill-kiro.md +0 -615
  1149. package/skills/graphify/skill-opencode.md +0 -608
  1150. package/skills/graphify/skill-pi.md +0 -615
  1151. package/skills/graphify/skill-trae.md +0 -614
  1152. package/skills/graphify/skill-vscode.md +0 -612
  1153. package/skills/graphify/skill-windows.md +0 -651
  1154. package/skills/graphify/skills/amp/references/add-watch.md +0 -56
  1155. package/skills/graphify/skills/amp/references/exports.md +0 -71
  1156. package/skills/graphify/skills/amp/references/extraction-spec.md +0 -68
  1157. package/skills/graphify/skills/amp/references/github-and-merge.md +0 -46
  1158. package/skills/graphify/skills/amp/references/hooks.md +0 -33
  1159. package/skills/graphify/skills/amp/references/query.md +0 -249
  1160. package/skills/graphify/skills/amp/references/transcribe.md +0 -48
  1161. package/skills/graphify/skills/amp/references/update.md +0 -179
  1162. package/skills/graphify/skills/claude/references/add-watch.md +0 -56
  1163. package/skills/graphify/skills/claude/references/exports.md +0 -71
  1164. package/skills/graphify/skills/claude/references/extraction-spec.md +0 -68
  1165. package/skills/graphify/skills/claude/references/github-and-merge.md +0 -46
  1166. package/skills/graphify/skills/claude/references/hooks.md +0 -33
  1167. package/skills/graphify/skills/claude/references/query.md +0 -103
  1168. package/skills/graphify/skills/claude/references/transcribe.md +0 -48
  1169. package/skills/graphify/skills/claude/references/update.md +0 -179
  1170. package/skills/graphify/skills/claw/references/add-watch.md +0 -56
  1171. package/skills/graphify/skills/claw/references/exports.md +0 -71
  1172. package/skills/graphify/skills/claw/references/extraction-spec.md +0 -29
  1173. package/skills/graphify/skills/claw/references/github-and-merge.md +0 -46
  1174. package/skills/graphify/skills/claw/references/hooks.md +0 -33
  1175. package/skills/graphify/skills/claw/references/query.md +0 -249
  1176. package/skills/graphify/skills/claw/references/transcribe.md +0 -48
  1177. package/skills/graphify/skills/claw/references/update.md +0 -179
  1178. package/skills/graphify/skills/codex/references/add-watch.md +0 -56
  1179. package/skills/graphify/skills/codex/references/exports.md +0 -71
  1180. package/skills/graphify/skills/codex/references/extraction-spec.md +0 -29
  1181. package/skills/graphify/skills/codex/references/github-and-merge.md +0 -46
  1182. package/skills/graphify/skills/codex/references/hooks.md +0 -33
  1183. package/skills/graphify/skills/codex/references/query.md +0 -249
  1184. package/skills/graphify/skills/codex/references/transcribe.md +0 -48
  1185. package/skills/graphify/skills/codex/references/update.md +0 -179
  1186. package/skills/graphify/skills/copilot/references/add-watch.md +0 -56
  1187. package/skills/graphify/skills/copilot/references/exports.md +0 -71
  1188. package/skills/graphify/skills/copilot/references/extraction-spec.md +0 -68
  1189. package/skills/graphify/skills/copilot/references/github-and-merge.md +0 -46
  1190. package/skills/graphify/skills/copilot/references/hooks.md +0 -33
  1191. package/skills/graphify/skills/copilot/references/query.md +0 -249
  1192. package/skills/graphify/skills/copilot/references/transcribe.md +0 -48
  1193. package/skills/graphify/skills/copilot/references/update.md +0 -179
  1194. package/skills/graphify/skills/droid/references/add-watch.md +0 -56
  1195. package/skills/graphify/skills/droid/references/exports.md +0 -71
  1196. package/skills/graphify/skills/droid/references/extraction-spec.md +0 -68
  1197. package/skills/graphify/skills/droid/references/github-and-merge.md +0 -46
  1198. package/skills/graphify/skills/droid/references/hooks.md +0 -33
  1199. package/skills/graphify/skills/droid/references/query.md +0 -249
  1200. package/skills/graphify/skills/droid/references/transcribe.md +0 -48
  1201. package/skills/graphify/skills/droid/references/update.md +0 -179
  1202. package/skills/graphify/skills/kilo/references/add-watch.md +0 -56
  1203. package/skills/graphify/skills/kilo/references/exports.md +0 -71
  1204. package/skills/graphify/skills/kilo/references/extraction-spec.md +0 -68
  1205. package/skills/graphify/skills/kilo/references/github-and-merge.md +0 -46
  1206. package/skills/graphify/skills/kilo/references/hooks.md +0 -33
  1207. package/skills/graphify/skills/kilo/references/query.md +0 -249
  1208. package/skills/graphify/skills/kilo/references/transcribe.md +0 -48
  1209. package/skills/graphify/skills/kilo/references/update.md +0 -179
  1210. package/skills/graphify/skills/kiro/references/add-watch.md +0 -56
  1211. package/skills/graphify/skills/kiro/references/exports.md +0 -71
  1212. package/skills/graphify/skills/kiro/references/extraction-spec.md +0 -29
  1213. package/skills/graphify/skills/kiro/references/github-and-merge.md +0 -46
  1214. package/skills/graphify/skills/kiro/references/hooks.md +0 -33
  1215. package/skills/graphify/skills/kiro/references/query.md +0 -249
  1216. package/skills/graphify/skills/kiro/references/transcribe.md +0 -48
  1217. package/skills/graphify/skills/kiro/references/update.md +0 -179
  1218. package/skills/graphify/skills/opencode/references/add-watch.md +0 -56
  1219. package/skills/graphify/skills/opencode/references/exports.md +0 -71
  1220. package/skills/graphify/skills/opencode/references/extraction-spec.md +0 -68
  1221. package/skills/graphify/skills/opencode/references/github-and-merge.md +0 -46
  1222. package/skills/graphify/skills/opencode/references/hooks.md +0 -33
  1223. package/skills/graphify/skills/opencode/references/query.md +0 -249
  1224. package/skills/graphify/skills/opencode/references/transcribe.md +0 -48
  1225. package/skills/graphify/skills/opencode/references/update.md +0 -179
  1226. package/skills/graphify/skills/pi/references/add-watch.md +0 -56
  1227. package/skills/graphify/skills/pi/references/exports.md +0 -71
  1228. package/skills/graphify/skills/pi/references/extraction-spec.md +0 -29
  1229. package/skills/graphify/skills/pi/references/github-and-merge.md +0 -46
  1230. package/skills/graphify/skills/pi/references/hooks.md +0 -33
  1231. package/skills/graphify/skills/pi/references/query.md +0 -249
  1232. package/skills/graphify/skills/pi/references/transcribe.md +0 -48
  1233. package/skills/graphify/skills/pi/references/update.md +0 -179
  1234. package/skills/graphify/skills/trae/references/add-watch.md +0 -56
  1235. package/skills/graphify/skills/trae/references/exports.md +0 -71
  1236. package/skills/graphify/skills/trae/references/extraction-spec.md +0 -68
  1237. package/skills/graphify/skills/trae/references/github-and-merge.md +0 -46
  1238. package/skills/graphify/skills/trae/references/hooks.md +0 -35
  1239. package/skills/graphify/skills/trae/references/query.md +0 -249
  1240. package/skills/graphify/skills/trae/references/transcribe.md +0 -48
  1241. package/skills/graphify/skills/trae/references/update.md +0 -179
  1242. package/skills/graphify/skills/vscode/references/add-watch.md +0 -56
  1243. package/skills/graphify/skills/vscode/references/exports.md +0 -71
  1244. package/skills/graphify/skills/vscode/references/extraction-spec.md +0 -68
  1245. package/skills/graphify/skills/vscode/references/github-and-merge.md +0 -46
  1246. package/skills/graphify/skills/vscode/references/hooks.md +0 -33
  1247. package/skills/graphify/skills/vscode/references/query.md +0 -249
  1248. package/skills/graphify/skills/vscode/references/transcribe.md +0 -48
  1249. package/skills/graphify/skills/vscode/references/update.md +0 -179
  1250. package/skills/graphify/skills/windows/references/add-watch.md +0 -56
  1251. package/skills/graphify/skills/windows/references/exports.md +0 -71
  1252. package/skills/graphify/skills/windows/references/extraction-spec.md +0 -68
  1253. package/skills/graphify/skills/windows/references/github-and-merge.md +0 -46
  1254. package/skills/graphify/skills/windows/references/hooks.md +0 -33
  1255. package/skills/graphify/skills/windows/references/query.md +0 -249
  1256. package/skills/graphify/skills/windows/references/transcribe.md +0 -48
  1257. package/skills/graphify/skills/windows/references/update.md +0 -179
  1258. package/skills/graphify/symbol_resolution.py +0 -538
  1259. package/skills/graphify/transcribe.py +0 -184
  1260. package/skills/graphify/tree_html.py +0 -582
  1261. package/skills/graphify/validate.py +0 -72
  1262. package/skills/graphify/watch.py +0 -898
  1263. package/skills/graphify/wiki.py +0 -282
@@ -1,1309 +0,0 @@
1
- # MCP stdio server - exposes graph query tools to Claude and other agents
2
- from __future__ import annotations
3
- import json
4
- import math
5
- import re
6
- import sys
7
- from pathlib import Path
8
- import networkx as nx
9
- from networkx.readwrite import json_graph
10
- from graphify.security import sanitize_label, check_graph_file_size_cap
11
- from graphify.build import edge_data
12
-
13
- try:
14
- import jieba as _jieba # type: ignore[import-untyped]
15
- except ImportError:
16
- _jieba = None
17
-
18
-
19
- def _load_graph(graph_path: str) -> nx.Graph:
20
- try:
21
- resolved = Path(graph_path).resolve()
22
- if resolved.suffix != ".json":
23
- raise ValueError(f"Graph path must be a .json file, got: {graph_path!r}")
24
- if not resolved.exists():
25
- raise FileNotFoundError(f"Graph file not found: {resolved}")
26
- check_graph_file_size_cap(resolved)
27
- safe = resolved
28
- data = json.loads(safe.read_text(encoding="utf-8"))
29
- if "links" not in data and "edges" in data:
30
- data = dict(data, links=data["edges"])
31
- data = {**data, "directed": True}
32
- try:
33
- return json_graph.node_link_graph(data, edges="links")
34
- except TypeError:
35
- return json_graph.node_link_graph(data)
36
- except (ValueError, FileNotFoundError) as exc:
37
- print(f"error: {exc}", file=sys.stderr)
38
- sys.exit(1)
39
- except json.JSONDecodeError as exc:
40
- print(f"error: graph.json is corrupted ({exc}). Re-run /graphify to rebuild.", file=sys.stderr)
41
- sys.exit(1)
42
-
43
-
44
- def _communities_from_graph(G: nx.Graph) -> dict[int, list[str]]:
45
- """Reconstruct community dict from community property stored on nodes."""
46
- communities: dict[int, list[str]] = {}
47
- for node_id, data in G.nodes(data=True):
48
- cid = data.get("community")
49
- if cid is not None:
50
- communities.setdefault(int(cid), []).append(node_id)
51
- return communities
52
-
53
-
54
- def _strip_diacritics(text: str) -> str:
55
- import unicodedata
56
- nfkd = unicodedata.normalize("NFKD", text)
57
- return "".join(c for c in nfkd if not unicodedata.combining(c))
58
-
59
-
60
- def _search_tokens(text: str) -> list[str]:
61
- """Split text into word tokens, stripping punctuation and diacritics."""
62
- return re.findall(r"\w+", _strip_diacritics(str(text)).lower())
63
-
64
-
65
- def _has_chinese(text: str) -> bool:
66
- return any("一" <= ch <= "鿿" for ch in text)
67
-
68
-
69
- def _segment_chinese(text: str) -> list[str]:
70
- """Segment Chinese text and keep the original term for exact matching."""
71
- if _jieba is not None:
72
- segments = [w for w in _jieba.cut(text) if len(w.strip()) > 0]
73
- else:
74
- segments = [text[i:i + 2] for i in range(len(text) - 1)] or [text]
75
- if len(text) > 1 and text not in segments:
76
- segments.append(text)
77
- return segments
78
-
79
-
80
- def _is_searchable(term: str) -> bool:
81
- """True if term is Chinese, non-English, or an English word longer than 2 chars."""
82
- if all("a" <= ch <= "z" for ch in term):
83
- return len(term) > 2
84
- return True
85
-
86
-
87
- def _query_terms(question: str) -> list[str]:
88
- """Split a query into searchable terms, segmenting Chinese text."""
89
- terms: list[str] = []
90
- for raw in question.split():
91
- if _has_chinese(raw):
92
- for seg in _segment_chinese(raw.lower().strip()):
93
- seg = seg.strip()
94
- if seg and _is_searchable(seg):
95
- terms.append(seg)
96
- else:
97
- # Strip punctuation without touching Unicode characters (avoid NFKD mangling non-Latin scripts)
98
- for tok in re.findall(r"\w+", raw.lower()):
99
- if _is_searchable(tok):
100
- terms.append(tok)
101
- return terms
102
-
103
-
104
- _EXACT_MATCH_BONUS = 1000.0
105
- _PREFIX_MATCH_BONUS = 100.0
106
- _SUBSTRING_MATCH_BONUS = 1.0
107
- _SOURCE_MATCH_BONUS = 0.5
108
-
109
-
110
- def _compute_idf(G: nx.Graph, terms: list[str]) -> dict[str, float]:
111
- """IDF weights for query terms, cached in G.graph['_idf_cache'].
112
-
113
- Common terms like 'error' or 'exception' that match hundreds of nodes get
114
- low weights; rare identifiers like 'FooBarService' get high weights.
115
- Cache is stored on the graph object itself so it auto-invalidates when
116
- _maybe_reload() replaces G with a new object.
117
- """
118
- cache: dict[str, float] = G.graph.setdefault("_idf_cache", {})
119
- N = G.number_of_nodes() or 1
120
- uncached = [t for t in terms if t not in cache]
121
- if uncached:
122
- df: dict[str, int] = {t: 0 for t in uncached}
123
- for _, data in G.nodes(data=True):
124
- norm_label = (
125
- data.get("norm_label") or _strip_diacritics(data.get("label") or "")
126
- ).lower()
127
- for t in uncached:
128
- if t in norm_label:
129
- df[t] += 1
130
- for t in uncached:
131
- cache[t] = math.log(1 + N / (1 + df[t]))
132
- return {t: cache.get(t, math.log(1 + N)) for t in terms}
133
-
134
-
135
- def _score_nodes(G: nx.Graph, terms: list[str]) -> list[tuple[float, str]]:
136
- scored = []
137
- norm_terms = [tok for t in terms for tok in _search_tokens(t)]
138
- idf = _compute_idf(G, norm_terms)
139
- # Whole-query string for full-label matching (mirrors _find_node's `term`).
140
- joined = " ".join(norm_terms)
141
- # Weight the full-query bonus by the rarest constituent term so a specific
142
- # multi-word label still outweighs common-token noise; floor at 1.0.
143
- joined_w = max((idf.get(t, 1.0) for t in norm_terms), default=1.0)
144
- for nid, data in G.nodes(data=True):
145
- norm_label = data.get("norm_label") or _strip_diacritics(data.get("label") or "").lower()
146
- bare_label = norm_label.rstrip("()")
147
- # Tokenized form of the label (punctuation stripped, same transform as the
148
- # query). norm_label may still carry punctuation like ':' or '-', which a
149
- # tokenized query can never equal; comparing token-joined forms on both
150
- # sides makes "uoce: dehumidifier driver" match query "uoce dehumidifier
151
- # driver".
152
- label_tokens = " ".join(_search_tokens(data.get("label") or ""))
153
- source = (data.get("source_file") or "").lower()
154
- score = 0.0
155
- # Full-query tier: a multi-word query that equals (or prefixes) the whole
156
- # label must dominate the per-token bag-of-words sums below, so `path`/
157
- # `query` resolve the same node `explain` does (via _find_node). Without
158
- # this, no single token equals a multi-word label, the per-token exact
159
- # tier never fires, and every node sharing the token set ties -> arbitrary
160
- # node-id sort -> wrong/disconnected endpoint -> false "No path found".
161
- if joined:
162
- nid_lower = nid.lower()
163
- if joined in (norm_label, bare_label, label_tokens, nid_lower):
164
- score += _EXACT_MATCH_BONUS * 10 * joined_w
165
- elif (
166
- norm_label.startswith(joined)
167
- or bare_label.startswith(joined)
168
- or label_tokens.startswith(joined)
169
- ):
170
- score += _PREFIX_MATCH_BONUS * 10 * joined_w
171
- for t in norm_terms:
172
- w = idf.get(t, 1.0)
173
- # Three-tier precedence: exact > prefix > substring (take the
174
- # strongest tier per term so a single term cannot double-count).
175
- if t == norm_label or t == bare_label:
176
- score += _EXACT_MATCH_BONUS * w
177
- elif norm_label.startswith(t) or bare_label.startswith(t):
178
- score += _PREFIX_MATCH_BONUS * w
179
- elif t in norm_label:
180
- score += _SUBSTRING_MATCH_BONUS * w
181
- if t in source:
182
- score += _SOURCE_MATCH_BONUS * w
183
- if score > 0:
184
- scored.append((score, nid))
185
- # Sort by score desc; break ties toward the shorter label so a concise exact
186
- # match beats a longer superset that happens to share the same score.
187
- scored.sort(key=lambda s: (-s[0], len(G.nodes[s[1]].get("label") or s[1]), s[1]))
188
- return scored
189
-
190
-
191
- def _pick_seeds(scored: list[tuple[float, str]], max_k: int = 3, gap_ratio: float = 0.2) -> list[str]:
192
- """Select BFS seed nodes, stopping when score drops too far below the top.
193
-
194
- Prevents high-frequency noise terms (error, exception) from stealing seed
195
- slots from a dominant identifier match. When FooBarService scores 1000 and
196
- error nodes score 1.0, only FooBarService is seeded — the score gap is 99.9%
197
- which is well above the 20% threshold that would allow additional seeds.
198
- """
199
- if not scored:
200
- return []
201
- top_score = scored[0][0]
202
- seeds = []
203
- for score, nid in scored[:max_k]:
204
- if seeds and score < top_score * gap_ratio:
205
- break
206
- seeds.append(nid)
207
- return seeds
208
-
209
-
210
- _CONTEXT_HINTS: tuple[tuple[str, tuple[str, ...]], ...] = (
211
- ("call", ("call", "calls", "called", "invoke", "invokes", "invoked")),
212
- ("import", ("import", "imports", "imported", "module", "modules")),
213
- ("field", ("field", "fields", "member", "members", "property", "properties")),
214
- ("parameter_type", ("parameter", "parameters", "param", "params", "argument", "arguments")),
215
- ("return_type", ("return", "returns", "returned")),
216
- ("generic_arg", ("generic", "generics", "template", "templates")),
217
- )
218
-
219
-
220
- _CONTEXT_FILTER_ALIASES: dict[str, str] = {
221
- "param": "parameter_type",
222
- "params": "parameter_type",
223
- "parameter": "parameter_type",
224
- "parameters": "parameter_type",
225
- "argument": "parameter_type",
226
- "arguments": "parameter_type",
227
- "arg": "parameter_type",
228
- "args": "parameter_type",
229
- "return": "return_type",
230
- "returns": "return_type",
231
- "returned": "return_type",
232
- "generic": "generic_arg",
233
- "generics": "generic_arg",
234
- "template": "generic_arg",
235
- "templates": "generic_arg",
236
- "annotation": "attribute",
237
- "annotations": "attribute",
238
- "decorator": "attribute",
239
- "decorators": "attribute",
240
- "calls": "call",
241
- "called": "call",
242
- "invoke": "call",
243
- "invocation": "call",
244
- "fields": "field",
245
- "property": "field",
246
- "properties": "field",
247
- "member": "field",
248
- "members": "field",
249
- "imports": "import",
250
- "imported": "import",
251
- "module": "import",
252
- "modules": "import",
253
- "exports": "export",
254
- "exported": "export",
255
- }
256
-
257
-
258
- def _normalize_context_filters(filters: list[str] | None) -> list[str]:
259
- if not filters:
260
- return []
261
- normalized: list[str] = []
262
- seen: set[str] = set()
263
- for value in filters:
264
- key = _strip_diacritics(str(value)).strip().lower()
265
- if not key:
266
- continue
267
- key = _CONTEXT_FILTER_ALIASES.get(key, key)
268
- if key not in seen:
269
- seen.add(key)
270
- normalized.append(key)
271
- return normalized
272
-
273
-
274
- def _infer_context_filters(question: str) -> list[str]:
275
- lowered = {
276
- _strip_diacritics(token).lower()
277
- for token in question.replace("?", " ").replace(",", " ").split()
278
- }
279
- inferred: list[str] = []
280
- for context, hints in _CONTEXT_HINTS:
281
- if any(hint in lowered for hint in hints):
282
- inferred.append(context)
283
- return inferred
284
-
285
-
286
- def _resolve_context_filters(question: str, explicit_filters: list[str] | None = None) -> tuple[list[str], str | None]:
287
- normalized = _normalize_context_filters(explicit_filters)
288
- if normalized:
289
- return normalized, "explicit"
290
- inferred = _infer_context_filters(question)
291
- if inferred:
292
- return inferred, "heuristic"
293
- return [], None
294
-
295
-
296
- def _filter_graph_by_context(G: nx.Graph, context_filters: list[str] | None) -> nx.Graph:
297
- filters = set(_normalize_context_filters(context_filters))
298
- if not filters:
299
- return G
300
- H = G.__class__()
301
- H.add_nodes_from(G.nodes(data=True))
302
- if isinstance(G, (nx.MultiGraph, nx.MultiDiGraph)):
303
- for u, v, key, data in G.edges(keys=True, data=True):
304
- if data.get("context") in filters:
305
- H.add_edge(u, v, key=key, **data)
306
- else:
307
- for u, v, data in G.edges(data=True):
308
- if data.get("context") in filters:
309
- H.add_edge(u, v, **data)
310
- return H
311
-
312
-
313
- def _bfs(G: nx.Graph, start_nodes: list[str], depth: int) -> tuple[set[str], list[tuple]]:
314
- # Compute hub threshold: nodes above this degree are not expanded as transit.
315
- # p99 of degree distribution, floored at 50 to avoid over-blocking small graphs.
316
- degrees = [G.degree(n) for n in G.nodes()]
317
- if degrees:
318
- degrees_sorted = sorted(degrees)
319
- p99_idx = int(len(degrees_sorted) * 0.99)
320
- hub_threshold = max(50, degrees_sorted[p99_idx])
321
- else:
322
- hub_threshold = 50
323
- seed_set = set(start_nodes)
324
- visited: set[str] = set(start_nodes)
325
- frontier = set(start_nodes)
326
- edges_seen: list[tuple] = []
327
- for _ in range(depth):
328
- next_frontier: set[str] = set()
329
- for n in frontier:
330
- # Don't expand through high-degree hubs (except seeds - a hub that
331
- # is the starting node should still be explored).
332
- if n not in seed_set and G.degree(n) >= hub_threshold:
333
- continue
334
- for neighbor in G.neighbors(n):
335
- if neighbor not in visited:
336
- next_frontier.add(neighbor)
337
- edges_seen.append((n, neighbor))
338
- visited.update(next_frontier)
339
- frontier = next_frontier
340
- return visited, edges_seen
341
-
342
-
343
- def _dfs(G: nx.Graph, start_nodes: list[str], depth: int) -> tuple[set[str], list[tuple]]:
344
- degrees = [G.degree(n) for n in G.nodes()]
345
- if degrees:
346
- degrees_sorted = sorted(degrees)
347
- p99_idx = int(len(degrees_sorted) * 0.99)
348
- hub_threshold = max(50, degrees_sorted[p99_idx])
349
- else:
350
- hub_threshold = 50
351
- seed_set = set(start_nodes)
352
- visited: set[str] = set()
353
- edges_seen: list[tuple] = []
354
- stack = [(n, 0) for n in reversed(start_nodes)]
355
- while stack:
356
- node, d = stack.pop()
357
- if node in visited or d > depth:
358
- continue
359
- visited.add(node)
360
- if node not in seed_set and G.degree(node) >= hub_threshold:
361
- continue
362
- for neighbor in G.neighbors(node):
363
- if neighbor not in visited:
364
- stack.append((neighbor, d + 1))
365
- edges_seen.append((node, neighbor))
366
- return visited, edges_seen
367
-
368
-
369
- def _subgraph_to_text(G: nx.Graph, nodes: set[str], edges: list[tuple], token_budget: int = 2000, *, seeds: list[str] | None = None) -> str:
370
- """Render subgraph as text, cutting at token_budget (approx 3 chars/token).
371
-
372
- seeds: exact-match nodes rendered first before the degree-sorted expansion,
373
- so the queried symbol always appears at the top of the output.
374
- """
375
- char_budget = token_budget * 3
376
- lines = []
377
- seed_set = set(seeds or [])
378
- ordered = [n for n in (seeds or []) if n in nodes] + \
379
- sorted(nodes - seed_set, key=lambda n: G.degree(n), reverse=True)
380
- for nid in ordered:
381
- d = G.nodes[nid]
382
- # Every LLM-derived field passes through sanitize_label before being
383
- # concatenated into MCP tool output (F-010): an attacker who controls a
384
- # corpus document can otherwise inject ANSI escapes, fake graphify-out
385
- # log lines, or prompt-injection markup into the model's context via
386
- # source_file / source_location / community.
387
- line = (
388
- f"NODE {sanitize_label(d.get('label', nid))} "
389
- f"[src={sanitize_label(str(d.get('source_file', '')))} "
390
- f"loc={sanitize_label(str(d.get('source_location', '')))} "
391
- f"community={sanitize_label(str(d.get('community', '')))}]"
392
- )
393
- lines.append(line)
394
- for u, v in edges:
395
- if u in nodes and v in nodes:
396
- raw = G[u][v]
397
- d = next(iter(raw.values()), {}) if isinstance(G, (nx.MultiGraph, nx.MultiDiGraph)) else raw
398
- context = d.get("context")
399
- context_suffix = f" context={sanitize_label(str(context))}" if context else ""
400
- line = (
401
- f"EDGE {sanitize_label(G.nodes[u].get('label', u))} "
402
- f"--{sanitize_label(str(d.get('relation', '')))} "
403
- f"[{sanitize_label(str(d.get('confidence', '')))}{context_suffix}]--> "
404
- f"{sanitize_label(G.nodes[v].get('label', v))}"
405
- )
406
- lines.append(line)
407
- output = "\n".join(lines)
408
- if len(output) > char_budget:
409
- cut_at = output[:char_budget].rfind("\n")
410
- cut_at = cut_at if cut_at > 0 else char_budget
411
- total_nodes = sum(1 for l in lines if l.startswith("NODE "))
412
- shown_nodes = output[:cut_at].count("\nNODE ") + (1 if output.startswith("NODE ") else 0)
413
- cut_count = total_nodes - shown_nodes
414
- output = (
415
- output[:cut_at]
416
- + f"\n... (truncated — {cut_count} more nodes cut by ~{token_budget}-token budget."
417
- f" Narrow with context_filter=['call'] or use get_node for a specific symbol)"
418
- )
419
- return output
420
-
421
-
422
- def _query_graph_text(
423
- G: nx.Graph,
424
- question: str,
425
- *,
426
- mode: str = "bfs",
427
- depth: int = 3,
428
- token_budget: int = 2000,
429
- context_filters: list[str] | None = None,
430
- ) -> str:
431
- terms = _query_terms(question)
432
- scored = _score_nodes(G, terms)
433
- start_nodes = _pick_seeds(scored)
434
- if not start_nodes:
435
- return "No matching nodes found."
436
- resolved_filters, filter_source = _resolve_context_filters(question, context_filters)
437
- traversal_graph = _filter_graph_by_context(G, resolved_filters)
438
- nodes, edges = _dfs(traversal_graph, start_nodes, depth) if mode == "dfs" else _bfs(traversal_graph, start_nodes, depth)
439
- header_parts = [
440
- f"Traversal: {mode.upper()} depth={depth}",
441
- f"Start: {[G.nodes[n].get('label', n) for n in start_nodes]}",
442
- ]
443
- if resolved_filters:
444
- header_parts.append(f"Context: {', '.join(resolved_filters)} ({filter_source})")
445
- header_parts.append(f"{len(nodes)} nodes found")
446
- header = " | ".join(header_parts) + "\n\n"
447
- return header + _subgraph_to_text(traversal_graph, nodes, edges, token_budget)
448
-
449
-
450
- def _find_node(G: nx.Graph, label: str) -> list[str]:
451
- """Return node IDs whose label or ID matches the search term (diacritic-insensitive).
452
-
453
- Results are ordered by three-tier precedence: exact match, then prefix match,
454
- then substring match. Node-ID exact matches are grouped with label exact matches.
455
- """
456
- term = " ".join(_search_tokens(label))
457
- if not term:
458
- return []
459
- exact: list[str] = []
460
- prefix: list[str] = []
461
- substring: list[str] = []
462
- for nid, d in G.nodes(data=True):
463
- norm_label = d.get("norm_label") or _strip_diacritics(d.get("label") or "").lower()
464
- bare_label = norm_label.rstrip("()")
465
- nid_lower = nid.lower()
466
- if term == norm_label or term == bare_label or term == nid_lower:
467
- exact.append(nid)
468
- elif norm_label.startswith(term) or bare_label.startswith(term) or nid_lower.startswith(term):
469
- prefix.append(nid)
470
- elif term in norm_label:
471
- substring.append(nid)
472
- return exact + prefix + substring
473
-
474
-
475
- def _filter_blank_stdin() -> None:
476
- """Filter blank lines from stdin before MCP reads it.
477
-
478
- Some MCP clients (Claude Desktop, etc.) send blank lines between JSON
479
- messages. The MCP stdio transport tries to parse every line as a
480
- JSONRPCMessage, so a bare newline triggers a Pydantic ValidationError.
481
- This installs an OS-level pipe that relays stdin while dropping blanks.
482
- """
483
- import os
484
- import threading
485
-
486
- r_fd, w_fd = os.pipe()
487
- saved_fd = os.dup(sys.stdin.fileno())
488
-
489
- def _relay() -> None:
490
- try:
491
- with open(saved_fd, "rb") as src, open(w_fd, "wb") as dst:
492
- for line in src:
493
- if line.strip():
494
- dst.write(line)
495
- dst.flush()
496
- except Exception:
497
- pass
498
-
499
- threading.Thread(target=_relay, daemon=True).start()
500
- os.dup2(r_fd, sys.stdin.fileno())
501
- os.close(r_fd)
502
- sys.stdin = open(0, "r", closefd=False)
503
-
504
-
505
- def _build_server(graph_path: str):
506
- """Build the configured low-level MCP Server (shared by every transport).
507
-
508
- All graph query tools and resources are registered here over a single
509
- ``mcp.server.Server`` instance; the caller picks the transport (stdio or
510
- Streamable HTTP) and runs it. Hot-reload of graph.json works the same way
511
- regardless of transport, since reloads happen inside the tool handlers.
512
- """
513
- import threading
514
-
515
- try:
516
- from mcp.server import Server
517
- from mcp import types
518
- from mcp.types import AnyUrl
519
- except ImportError as e:
520
- raise ImportError('mcp not installed. Run: pip install "graphifyy[mcp]"') from e
521
-
522
- G = _load_graph(graph_path)
523
- communities = _communities_from_graph(G)
524
-
525
- # Hot-reload state: mtime+size key lets us detect graph.json changes without
526
- # polling. Initialised from the file stat at startup so the first tool call
527
- # never triggers a redundant reload.
528
- _reload_lock = threading.Lock()
529
- try:
530
- _s = Path(graph_path).stat()
531
- _reload_state: dict = {"mtime_ns": _s.st_mtime_ns, "size": _s.st_size}
532
- except FileNotFoundError:
533
- _reload_state = {"mtime_ns": 0, "size": -1}
534
-
535
- def _maybe_reload() -> None:
536
- nonlocal G, communities
537
- try:
538
- s = Path(graph_path).stat()
539
- key = (s.st_mtime_ns, s.st_size)
540
- except FileNotFoundError:
541
- return
542
- if key == (_reload_state["mtime_ns"], _reload_state["size"]):
543
- return
544
- with _reload_lock:
545
- try:
546
- s = Path(graph_path).stat()
547
- key = (s.st_mtime_ns, s.st_size)
548
- except FileNotFoundError:
549
- return
550
- if key == (_reload_state["mtime_ns"], _reload_state["size"]):
551
- return # another thread already reloaded
552
- try:
553
- new_G = _load_graph(graph_path)
554
- except SystemExit:
555
- return # keep serving stale graph on transient read error
556
- G = new_G
557
- communities = _communities_from_graph(new_G)
558
- _reload_state["mtime_ns"], _reload_state["size"] = key
559
-
560
- server = Server("graphify")
561
-
562
- @server.list_tools()
563
- async def list_tools() -> list[types.Tool]:
564
- return [
565
- types.Tool(
566
- name="query_graph",
567
- description="Search the knowledge graph using BFS or DFS. Returns relevant nodes and edges as text context.",
568
- inputSchema={
569
- "type": "object",
570
- "properties": {
571
- "question": {"type": "string", "description": "Natural language question or keyword search"},
572
- "mode": {"type": "string", "enum": ["bfs", "dfs"], "default": "bfs",
573
- "description": "bfs=broad context, dfs=trace a specific path"},
574
- "depth": {"type": "integer", "default": 3, "description": "Traversal depth (1-6)"},
575
- "token_budget": {"type": "integer", "default": 2000, "description": "Max output tokens"},
576
- "context_filter": {
577
- "type": "array",
578
- "items": {"type": "string"},
579
- "description": "Optional explicit edge-context filter, e.g. ['call', 'field']",
580
- },
581
- },
582
- "required": ["question"],
583
- },
584
- ),
585
- types.Tool(
586
- name="get_node",
587
- description="Get full details for a specific node by label or ID.",
588
- inputSchema={
589
- "type": "object",
590
- "properties": {"label": {"type": "string", "description": "Node label or ID to look up"}},
591
- "required": ["label"],
592
- },
593
- ),
594
- types.Tool(
595
- name="get_neighbors",
596
- description="Get all direct neighbors of a node with edge details.",
597
- inputSchema={
598
- "type": "object",
599
- "properties": {
600
- "label": {"type": "string"},
601
- "relation_filter": {"type": "string", "description": "Optional: filter by relation type"},
602
- },
603
- "required": ["label"],
604
- },
605
- ),
606
- types.Tool(
607
- name="get_community",
608
- description="Get all nodes in a community by community ID.",
609
- inputSchema={
610
- "type": "object",
611
- "properties": {"community_id": {"type": "integer", "description": "Community ID (0-indexed by size)"}},
612
- "required": ["community_id"],
613
- },
614
- ),
615
- types.Tool(
616
- name="god_nodes",
617
- description="Return the most connected nodes - the core abstractions of the knowledge graph.",
618
- inputSchema={"type": "object", "properties": {"top_n": {"type": "integer", "default": 10}}},
619
- ),
620
- types.Tool(
621
- name="graph_stats",
622
- description="Return summary statistics: node count, edge count, communities, confidence breakdown.",
623
- inputSchema={"type": "object", "properties": {}},
624
- ),
625
- types.Tool(
626
- name="shortest_path",
627
- description="Find the shortest path between two concepts in the knowledge graph.",
628
- inputSchema={
629
- "type": "object",
630
- "properties": {
631
- "source": {"type": "string", "description": "Source concept label or keyword"},
632
- "target": {"type": "string", "description": "Target concept label or keyword"},
633
- "max_hops": {"type": "integer", "default": 8, "description": "Maximum hops to consider"},
634
- },
635
- "required": ["source", "target"],
636
- },
637
- ),
638
- types.Tool(
639
- name="list_prs",
640
- description=(
641
- "List open GitHub PRs with CI status, review state, and graph impact "
642
- "(which communities each PR touches, blast radius). Use this before starting "
643
- "work to check if a PR already covers the area you're about to change."
644
- ),
645
- inputSchema={
646
- "type": "object",
647
- "properties": {
648
- "base": {"type": "string", "description": "Base branch to filter PRs by (auto-detected if omitted)"},
649
- "repo": {"type": "string", "description": "GitHub repo (owner/repo). Defaults to current repo."},
650
- },
651
- },
652
- ),
653
- types.Tool(
654
- name="get_pr_impact",
655
- description=(
656
- "Get detailed graph impact for a specific PR: which files it changes, "
657
- "which knowledge-graph communities are affected, and how many nodes are touched. "
658
- "Use this to assess merge risk or check for overlap with your current work."
659
- ),
660
- inputSchema={
661
- "type": "object",
662
- "properties": {
663
- "pr_number": {"type": "integer", "description": "PR number to analyse"},
664
- "repo": {"type": "string", "description": "GitHub repo (owner/repo). Defaults to current repo."},
665
- },
666
- "required": ["pr_number"],
667
- },
668
- ),
669
- types.Tool(
670
- name="triage_prs",
671
- description=(
672
- "Return all actionable open PRs (correct base, not stale) with full graph impact data "
673
- "so you can reason about review priority, merge order, and conflict risk. "
674
- "Call this when the user asks 'what PRs should I review?' or 'what's ready to merge?'"
675
- ),
676
- inputSchema={
677
- "type": "object",
678
- "properties": {
679
- "base": {"type": "string", "description": "Base branch to filter PRs by (auto-detected if omitted)"},
680
- "repo": {"type": "string", "description": "GitHub repo (owner/repo). Defaults to current repo."},
681
- },
682
- },
683
- ),
684
- ]
685
-
686
- def _tool_query_graph(arguments: dict) -> str:
687
- import time as _time
688
- from graphify import querylog
689
- question = arguments["question"]
690
- mode = arguments.get("mode", "bfs")
691
- depth = min(int(arguments.get("depth", 3)), 6)
692
- budget = int(arguments.get("token_budget", 2000))
693
- context_filter = arguments.get("context_filter")
694
- _t0 = _time.perf_counter()
695
- result = _query_graph_text(
696
- G,
697
- question,
698
- mode=mode,
699
- depth=depth,
700
- token_budget=budget,
701
- context_filters=context_filter,
702
- )
703
- querylog.log_query(
704
- kind="mcp_query",
705
- question=question,
706
- corpus=str(graph_path),
707
- result=result,
708
- mode=mode,
709
- depth=depth,
710
- token_budget=budget,
711
- duration_ms=(_time.perf_counter() - _t0) * 1000,
712
- )
713
- return result
714
-
715
- def _tool_get_node(arguments: dict) -> str:
716
- label = arguments["label"].lower()
717
- matches = [(nid, d) for nid, d in G.nodes(data=True)
718
- if label in (d.get("label") or "").lower() or label == nid.lower()]
719
- if not matches:
720
- return f"No node matching '{label}' found."
721
- nid, d = matches[0]
722
- # Sanitise every LLM-derived field before concatenation (F-010).
723
- return "\n".join([
724
- f"Node: {sanitize_label(d.get('label', nid))}",
725
- f" ID: {sanitize_label(nid)}",
726
- f" Source: {sanitize_label(str(d.get('source_file', '')))} {sanitize_label(str(d.get('source_location', '')))}",
727
- f" Type: {sanitize_label(str(d.get('file_type', '')))}",
728
- f" Community: {sanitize_label(str(d.get('community', '')))}",
729
- f" Degree: {G.degree(nid)}",
730
- ])
731
-
732
- def _tool_get_neighbors(arguments: dict) -> str:
733
- label = arguments["label"].lower()
734
- rel_filter = arguments.get("relation_filter", "").lower()
735
- matches = _find_node(G, label)
736
- if not matches:
737
- return f"No node matching '{label}' found."
738
- nid = matches[0]
739
- lines = [f"Neighbors of {sanitize_label(G.nodes[nid].get('label', nid))}:"]
740
- for nb in G.successors(nid):
741
- d = edge_data(G, nid, nb)
742
- rel = d.get("relation", "")
743
- if rel_filter and rel_filter not in rel.lower():
744
- continue
745
- lines.append(
746
- f" --> {sanitize_label(G.nodes[nb].get('label', nb))} "
747
- f"[{sanitize_label(str(rel))}] [{sanitize_label(str(d.get('confidence', '')))}]"
748
- )
749
- for nb in G.predecessors(nid):
750
- d = edge_data(G, nb, nid)
751
- rel = d.get("relation", "")
752
- if rel_filter and rel_filter not in rel.lower():
753
- continue
754
- lines.append(
755
- f" <-- {sanitize_label(G.nodes[nb].get('label', nb))} "
756
- f"[{sanitize_label(str(rel))}] [{sanitize_label(str(d.get('confidence', '')))}]"
757
- )
758
- return "\n".join(lines)
759
-
760
- def _tool_get_community(arguments: dict) -> str:
761
- cid = int(arguments["community_id"])
762
- nodes = communities.get(cid, [])
763
- if not nodes:
764
- return f"Community {cid} not found."
765
- lines = [f"Community {cid} ({len(nodes)} nodes):"]
766
- for n in nodes:
767
- d = G.nodes[n]
768
- # Sanitise label and source_file (F-010).
769
- lines.append(
770
- f" {sanitize_label(d.get('label', n))} "
771
- f"[{sanitize_label(str(d.get('source_file', '')))}]"
772
- )
773
- return "\n".join(lines)
774
-
775
- def _tool_god_nodes(arguments: dict) -> str:
776
- from graphify.analyze import god_nodes as _god_nodes
777
- nodes = _god_nodes(G, top_n=int(arguments.get("top_n", 10)))
778
- lines = ["God nodes (most connected):"]
779
- lines += [f" {i}. {n['label']} - {n['degree']} edges" for i, n in enumerate(nodes, 1)]
780
- return "\n".join(lines)
781
-
782
- def _tool_graph_stats(_: dict) -> str:
783
- confs = [d.get("confidence", "EXTRACTED") for _, _, d in G.edges(data=True)]
784
- total = len(confs) or 1
785
- return (
786
- f"Nodes: {G.number_of_nodes()}\n"
787
- f"Edges: {G.number_of_edges()}\n"
788
- f"Communities: {len(communities)}\n"
789
- f"EXTRACTED: {round(confs.count('EXTRACTED')/total*100)}%\n"
790
- f"INFERRED: {round(confs.count('INFERRED')/total*100)}%\n"
791
- f"AMBIGUOUS: {round(confs.count('AMBIGUOUS')/total*100)}%\n"
792
- )
793
-
794
- def _tool_shortest_path(arguments: dict) -> str:
795
- src_scored = _score_nodes(G, [t.lower() for t in arguments["source"].split()])
796
- tgt_scored = _score_nodes(G, [t.lower() for t in arguments["target"].split()])
797
- if not src_scored:
798
- return f"No node matching source '{arguments['source']}' found."
799
- if not tgt_scored:
800
- return f"No node matching target '{arguments['target']}' found."
801
- src_nid, tgt_nid = src_scored[0][1], tgt_scored[0][1]
802
- # Ambiguity guard: when both queries resolve to the same node, the
803
- # shortest path is trivially zero hops, which is almost never what the
804
- # caller wanted (see bug #828).
805
- if src_nid == tgt_nid:
806
- return (
807
- f"'{arguments['source']}' and '{arguments['target']}' both resolved to "
808
- f"the same node '{src_nid}'. Use a more specific label or the exact node ID."
809
- )
810
- warnings: list[str] = []
811
- for name, scored in (("source", src_scored), ("target", tgt_scored)):
812
- if len(scored) >= 2:
813
- top, runner = scored[0][0], scored[1][0]
814
- if top > 0 and (top - runner) / top < 0.10:
815
- warnings.append(
816
- f"warning: {name} match was ambiguous "
817
- f"(top score {top:g}, runner-up {runner:g})"
818
- )
819
- max_hops = int(arguments.get("max_hops", 8))
820
- try:
821
- # Use undirected view for path-finding (works regardless of query src/tgt order)
822
- path_nodes = nx.shortest_path(G.to_undirected(as_view=True), src_nid, tgt_nid)
823
- except (nx.NetworkXNoPath, nx.NodeNotFound):
824
- return f"No path found between '{G.nodes[src_nid].get('label', src_nid)}' and '{G.nodes[tgt_nid].get('label', tgt_nid)}'."
825
- hops = len(path_nodes) - 1
826
- if hops > max_hops:
827
- return f"Path exceeds max_hops={max_hops} ({hops} hops found)."
828
- segments = []
829
- for i in range(len(path_nodes) - 1):
830
- u, v = path_nodes[i], path_nodes[i + 1]
831
- if G.has_edge(u, v):
832
- edata = edge_data(G, u, v)
833
- forward = True
834
- else:
835
- edata = edge_data(G, v, u)
836
- forward = False
837
- rel = edata.get("relation", "")
838
- conf = edata.get("confidence", "")
839
- conf_str = f" [{conf}]" if conf else ""
840
- if i == 0:
841
- segments.append(G.nodes[u].get("label", u))
842
- if forward:
843
- segments.append(f"--{rel}{conf_str}--> {G.nodes[v].get('label', v)}")
844
- else:
845
- segments.append(f"<--{rel}{conf_str}-- {G.nodes[v].get('label', v)}")
846
- prefix = ("\n".join(warnings) + "\n") if warnings else ""
847
- return prefix + f"Shortest path ({hops} hops):\n " + " ".join(segments)
848
-
849
- def _tool_list_prs(arguments: dict) -> str:
850
- from graphify.prs import fetch_prs, fetch_worktrees, format_prs_text, _detect_default_branch
851
- repo = arguments.get("repo") or None
852
- base = arguments.get("base") or _detect_default_branch(repo)
853
- try:
854
- prs = fetch_prs(repo=repo, base=base)
855
- except RuntimeError as e:
856
- return f"Error: {e}"
857
- worktrees = fetch_worktrees()
858
- for pr in prs:
859
- pr.worktree_path = worktrees.get(pr.branch)
860
- return format_prs_text(prs, base)
861
-
862
- def _tool_get_pr_impact(arguments: dict) -> str:
863
- from graphify.prs import fetch_pr_files, compute_pr_impact, _gh, _parse_ci
864
- number = int(arguments["pr_number"])
865
- repo = arguments.get("repo") or None
866
- # Use gh pr view directly — works for any base branch, not just the default
867
- view_args = ["pr", "view", str(number), "--json",
868
- "title,headRefName,baseRefName,author,isDraft,reviewDecision,statusCheckRollup,updatedAt"]
869
- if repo:
870
- view_args += ["--repo", repo]
871
- pr_data = _gh(*view_args)
872
- if pr_data is None:
873
- return f"PR #{number} not found or gh not authenticated."
874
- files = fetch_pr_files(number, repo)
875
- if not files:
876
- return f"PR #{number}: no changed files found (may require gh auth)."
877
- comms, nodes = compute_pr_impact(files, G)
878
- ci = _parse_ci(pr_data.get("statusCheckRollup") or [])
879
- lines = [
880
- f"PR #{number}: {pr_data['title']}",
881
- f"CI: {ci} Review: {pr_data.get('reviewDecision') or 'none'}",
882
- f"Base: {pr_data['baseRefName']} Author: {(pr_data.get('author') or {}).get('login', '?')}",
883
- f"\nGraph impact: {nodes} nodes across {len(comms)} communities",
884
- f"Communities touched: {comms}",
885
- f"Files changed ({len(files)}):",
886
- ]
887
- lines += [f" {f}" for f in files[:20]]
888
- if len(files) > 20:
889
- lines.append(f" … and {len(files) - 20} more")
890
- return "\n".join(lines)
891
-
892
- def _tool_triage_prs(arguments: dict) -> str:
893
- from concurrent.futures import ThreadPoolExecutor, as_completed
894
- from graphify.prs import fetch_prs, fetch_worktrees, fetch_pr_files, compute_pr_impact, _STATUS_ORDER, _detect_default_branch
895
- repo = arguments.get("repo") or None
896
- base = arguments.get("base") or _detect_default_branch(repo)
897
- try:
898
- prs = fetch_prs(repo=repo, base=base)
899
- except RuntimeError as e:
900
- return f"Error: {e}"
901
- worktrees = fetch_worktrees()
902
- for pr in prs:
903
- pr.worktree_path = worktrees.get(pr.branch)
904
- actionable = [p for p in prs if p.base_branch == base and p.status not in ("WRONG-BASE", "STALE")]
905
- if not actionable:
906
- return f"No actionable PRs targeting {base}."
907
- # Fetch diffs concurrently then compute graph impact using in-memory G
908
- workers = min(8, len(actionable))
909
- with ThreadPoolExecutor(max_workers=workers) as pool:
910
- future_to_pr = {pool.submit(fetch_pr_files, pr.number, repo): pr for pr in actionable}
911
- for fut in as_completed(future_to_pr):
912
- pr = future_to_pr[fut]
913
- try:
914
- files = fut.result()
915
- except Exception:
916
- files = []
917
- if files:
918
- pr.files_changed = files
919
- pr.communities_touched, pr.nodes_affected = compute_pr_impact(files, G)
920
- header = (
921
- f"Actionable PRs targeting {base}: {len(actionable)}\n"
922
- "Rank these by review priority. Higher blast_radius = more graph communities affected = higher merge risk.\n"
923
- )
924
- lines = [header]
925
- for p in sorted(actionable, key=lambda x: (_STATUS_ORDER.index(x.status) if x.status in _STATUS_ORDER else 99)):
926
- impact = f" blast_radius={p.blast_radius}" if p.blast_radius else ""
927
- wt = f" worktree={p.worktree_path}" if p.worktree_path else ""
928
- lines.append(
929
- f"PR #{p.number} [{p.status}] CI={p.ci_status} review={p.review_decision or 'none'} "
930
- f"age={p.days_old}d author={p.author}{impact}{wt}\n title: {p.title}"
931
- )
932
- return "\n\n".join(lines)
933
-
934
- _handlers = {
935
- "query_graph": _tool_query_graph,
936
- "get_node": _tool_get_node,
937
- "get_neighbors": _tool_get_neighbors,
938
- "get_community": _tool_get_community,
939
- "god_nodes": _tool_god_nodes,
940
- "graph_stats": _tool_graph_stats,
941
- "shortest_path": _tool_shortest_path,
942
- "list_prs": _tool_list_prs,
943
- "get_pr_impact": _tool_get_pr_impact,
944
- "triage_prs": _tool_triage_prs,
945
- }
946
-
947
- def _load_community_labels() -> dict[int, str]:
948
- labels_path = Path(graph_path).parent / ".graphify_labels.json"
949
- if labels_path.exists():
950
- try:
951
- return {int(k): v for k, v in json.loads(labels_path.read_text(encoding="utf-8")).items()}
952
- except Exception:
953
- pass
954
- return {cid: f"Community {cid}" for cid in communities}
955
-
956
- @server.list_resources()
957
- async def list_resources() -> list[types.Resource]:
958
- return [
959
- types.Resource(uri=AnyUrl("graphify://report"), name="Graph Report", description="Full GRAPH_REPORT.md", mimeType="text/markdown"),
960
- types.Resource(uri=AnyUrl("graphify://stats"), name="Graph Stats", description="Node/edge/community counts and confidence breakdown", mimeType="text/plain"),
961
- types.Resource(uri=AnyUrl("graphify://god-nodes"), name="God Nodes", description="Top 10 most-connected nodes", mimeType="text/plain"),
962
- types.Resource(uri=AnyUrl("graphify://surprises"), name="Surprising Connections", description="Cross-community surprising connections", mimeType="text/plain"),
963
- types.Resource(uri=AnyUrl("graphify://audit"), name="Confidence Audit", description="EXTRACTED/INFERRED/AMBIGUOUS edge breakdown", mimeType="text/plain"),
964
- types.Resource(uri=AnyUrl("graphify://questions"), name="Suggested Questions", description="Suggested questions for this codebase", mimeType="text/plain"),
965
- ]
966
-
967
- @server.read_resource()
968
- async def read_resource(uri: AnyUrl) -> str:
969
- _maybe_reload()
970
- uri_str = str(uri)
971
- if uri_str == "graphify://report":
972
- report_path = Path(graph_path).parent / "GRAPH_REPORT.md"
973
- if report_path.exists():
974
- return report_path.read_text(encoding="utf-8")
975
- return "GRAPH_REPORT.md not found. Run graphify extract first."
976
- if uri_str == "graphify://stats":
977
- return _tool_graph_stats({})
978
- if uri_str == "graphify://god-nodes":
979
- return _tool_god_nodes({"top_n": 10})
980
- if uri_str == "graphify://surprises":
981
- try:
982
- from graphify.analyze import surprising_connections
983
- surprises = surprising_connections(G, communities, top_n=10)
984
- if not surprises:
985
- return "No surprising connections found."
986
- lines = ["Surprising cross-community connections:"]
987
- for s in surprises:
988
- lines.append(f" {s.get('source', '')} <-> {s.get('target', '')} [{s.get('relation', '')}]")
989
- return "\n".join(lines)
990
- except Exception as exc:
991
- return f"Could not compute surprising connections: {exc}"
992
- if uri_str == "graphify://audit":
993
- confs = [d.get("confidence", "EXTRACTED") for _, _, d in G.edges(data=True)]
994
- total = len(confs) or 1
995
- return (
996
- f"Total edges: {total}\n"
997
- f"EXTRACTED: {confs.count('EXTRACTED')} ({round(confs.count('EXTRACTED')/total*100)}%)\n"
998
- f"INFERRED: {confs.count('INFERRED')} ({round(confs.count('INFERRED')/total*100)}%)\n"
999
- f"AMBIGUOUS: {confs.count('AMBIGUOUS')} ({round(confs.count('AMBIGUOUS')/total*100)}%)\n"
1000
- )
1001
- if uri_str == "graphify://questions":
1002
- try:
1003
- from graphify.analyze import suggest_questions
1004
- community_labels = _load_community_labels()
1005
- questions = suggest_questions(G, communities, community_labels, top_n=10)
1006
- if not questions:
1007
- return "No suggested questions available."
1008
- lines = ["Suggested questions:"]
1009
- for q in questions:
1010
- if isinstance(q, dict):
1011
- lines.append(f" - {q.get('question', '')}")
1012
- else:
1013
- lines.append(f" - {q}")
1014
- return "\n".join(lines)
1015
- except Exception as exc:
1016
- return f"Could not generate questions: {exc}"
1017
- raise ValueError(f"Unknown resource: {uri_str}")
1018
-
1019
- @server.call_tool()
1020
- async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
1021
- _maybe_reload()
1022
- handler = _handlers.get(name)
1023
- if not handler:
1024
- return [types.TextContent(type="text", text=f"Unknown tool: {name}")]
1025
- try:
1026
- return [types.TextContent(type="text", text=handler(arguments))]
1027
- except Exception as exc:
1028
- return [types.TextContent(type="text", text=f"Error executing {name}: {exc}")]
1029
-
1030
- return server
1031
-
1032
-
1033
- def serve(graph_path: str = "graphify-out/graph.json") -> None:
1034
- """Start the MCP server over stdio (the default, per-developer transport)."""
1035
- try:
1036
- from mcp.server.stdio import stdio_server
1037
- except ImportError as e:
1038
- raise ImportError('mcp not installed. Run: pip install "graphifyy[mcp]"') from e
1039
- import asyncio
1040
-
1041
- server = _build_server(graph_path)
1042
-
1043
- async def main() -> None:
1044
- async with stdio_server() as streams:
1045
- await server.run(streams[0], streams[1], server.create_initialization_options())
1046
-
1047
- _filter_blank_stdin()
1048
- asyncio.run(main())
1049
-
1050
-
1051
- class _MCPASGIApp:
1052
- """Raw-ASGI wrapper around the Streamable HTTP session manager.
1053
-
1054
- Passed to a Starlette ``Route`` as a class instance (not a function) so
1055
- Starlette treats it as an ASGI app: it serves the exact mount path for all
1056
- methods (GET/POST/DELETE) with no request/response wrapping and no
1057
- trailing-slash redirect — mirroring how FastMCP mounts the same manager.
1058
- """
1059
-
1060
- def __init__(self, manager) -> None:
1061
- self._manager = manager
1062
-
1063
- async def __call__(self, scope, receive, send) -> None:
1064
- await self._manager.handle_request(scope, receive, send)
1065
-
1066
-
1067
- class _ApiKeyMiddleware:
1068
- """Pure-ASGI API-key gate for the HTTP transport.
1069
-
1070
- Implemented as raw ASGI (not Starlette's BaseHTTPMiddleware) on purpose:
1071
- BaseHTTPMiddleware buffers responses and breaks the Streamable HTTP SSE
1072
- stream. This short-circuits with 401 before the request ever reaches the
1073
- session manager, leaving the streaming path untouched for authorized calls.
1074
- """
1075
-
1076
- def __init__(self, app, api_key: str) -> None:
1077
- self.app = app
1078
- self._expected = api_key.encode("utf-8")
1079
-
1080
- async def __call__(self, scope, receive, send) -> None:
1081
- if scope["type"] != "http":
1082
- await self.app(scope, receive, send)
1083
- return
1084
- import hmac
1085
- headers = dict(scope.get("headers") or [])
1086
- provided = headers.get(b"x-api-key")
1087
- if provided is None:
1088
- # RFC 6750: the auth scheme token is case-insensitive.
1089
- scheme, _, token = headers.get(b"authorization", b"").partition(b" ")
1090
- if scheme.lower() == b"bearer" and token:
1091
- provided = token.strip()
1092
- # Constant-time compare; reject when no key was supplied at all.
1093
- if provided is None or not hmac.compare_digest(provided, self._expected):
1094
- body = b'{"error": "unauthorized"}'
1095
- await send({
1096
- "type": "http.response.start",
1097
- "status": 401,
1098
- "headers": [
1099
- (b"content-type", b"application/json"),
1100
- (b"content-length", str(len(body)).encode("ascii")),
1101
- ],
1102
- })
1103
- await send({"type": "http.response.body", "body": body})
1104
- return
1105
- await self.app(scope, receive, send)
1106
-
1107
-
1108
- def _build_http_app(
1109
- graph_path: str,
1110
- *,
1111
- host: str = "127.0.0.1",
1112
- port: int = 8080,
1113
- api_key: str | None = None,
1114
- path: str = "/mcp",
1115
- json_response: bool = False,
1116
- stateless: bool = False,
1117
- session_timeout: float | None = 3600.0,
1118
- ):
1119
- """Build the Starlette ASGI app for the Streamable HTTP transport.
1120
-
1121
- Split out from :func:`serve_http` (which blocks on uvicorn) so the wiring
1122
- can be exercised with an in-process ASGI test client.
1123
-
1124
- ``session_timeout`` reaps stateful sessions idle for that many seconds so a
1125
- long-running shared server does not leak memory when IDE clients disconnect
1126
- without sending a DELETE. ``None`` (or <= 0) disables reaping; it is forced
1127
- to ``None`` in stateless mode, which has no sessions to reap.
1128
- """
1129
- try:
1130
- import contextlib
1131
-
1132
- from starlette.applications import Starlette
1133
- from starlette.middleware import Middleware
1134
- from starlette.routing import Route
1135
-
1136
- from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
1137
- from mcp.server.transport_security import TransportSecuritySettings
1138
- except ImportError as e:
1139
- raise ImportError(
1140
- 'HTTP transport needs the mcp extra (mcp + starlette + uvicorn). '
1141
- 'Run: pip install "graphifyy[mcp]"'
1142
- ) from e
1143
-
1144
- # A blank key (e.g. --api-key "" or an empty GRAPHIFY_API_KEY) must not be
1145
- # mistaken for "auth on" — normalize it to None so the gate is unambiguous.
1146
- api_key = (api_key or "").strip() or None
1147
-
1148
- server = _build_server(graph_path)
1149
-
1150
- # DNS-rebinding protection. When the operator binds a wildcard address they
1151
- # are intentionally exposing the server, so accept any Host header; for a
1152
- # loopback/specific bind, restrict Host to that address (with and without
1153
- # the port) plus the localhost aliases.
1154
- if host in ("0.0.0.0", "::", ""):
1155
- security = TransportSecuritySettings(enable_dns_rebinding_protection=False)
1156
- else:
1157
- allowed = {host, "localhost", "127.0.0.1"}
1158
- allowed |= {f"{h}:{port}" for h in list(allowed)}
1159
- security = TransportSecuritySettings(allowed_hosts=sorted(allowed))
1160
-
1161
- # The SDK rejects a non-positive timeout and forbids one in stateless mode.
1162
- idle_timeout = None if (stateless or not session_timeout or session_timeout <= 0) else session_timeout
1163
-
1164
- manager = StreamableHTTPSessionManager(
1165
- app=server,
1166
- json_response=json_response,
1167
- stateless=stateless,
1168
- security_settings=security,
1169
- session_idle_timeout=idle_timeout,
1170
- )
1171
-
1172
- @contextlib.asynccontextmanager
1173
- async def lifespan(_app):
1174
- # The session manager owns an anyio task group that must wrap the whole
1175
- # server lifetime, so enter it here rather than per-request.
1176
- async with manager.run():
1177
- yield
1178
-
1179
- middleware = []
1180
- if api_key:
1181
- middleware.append(Middleware(_ApiKeyMiddleware, api_key=api_key))
1182
-
1183
- return Starlette(
1184
- routes=[Route(path, endpoint=_MCPASGIApp(manager))],
1185
- middleware=middleware,
1186
- lifespan=lifespan,
1187
- )
1188
-
1189
-
1190
- def serve_http(
1191
- graph_path: str = "graphify-out/graph.json",
1192
- *,
1193
- host: str = "127.0.0.1",
1194
- port: int = 8080,
1195
- api_key: str | None = None,
1196
- path: str = "/mcp",
1197
- json_response: bool = False,
1198
- stateless: bool = False,
1199
- session_timeout: float | None = 3600.0,
1200
- ) -> None:
1201
- """Start the MCP server over Streamable HTTP (MCP spec 2025-03-26).
1202
-
1203
- Serves the same tools/resources as the stdio transport, so a single shared
1204
- process can host the graph for a whole team. Clients point their IDE MCP
1205
- config at ``http://<host>:<port><path>`` (default ``/mcp``).
1206
-
1207
- ``api_key`` (or the ``GRAPHIFY_API_KEY`` env var) enables a simple header
1208
- check (``Authorization: Bearer <key>`` or ``X-API-Key: <key>``). OAuth is a
1209
- deliberate follow-up. Binding ``0.0.0.0`` exposes the server beyond
1210
- localhost — set an api_key when you do.
1211
- """
1212
- try:
1213
- import uvicorn
1214
- except ImportError as e:
1215
- raise ImportError(
1216
- 'HTTP transport needs the mcp extra (mcp + starlette + uvicorn). '
1217
- 'Run: pip install "graphifyy[mcp]"'
1218
- ) from e
1219
-
1220
- api_key = (api_key or "").strip() or None
1221
-
1222
- app = _build_http_app(
1223
- graph_path,
1224
- host=host,
1225
- port=port,
1226
- api_key=api_key,
1227
- path=path,
1228
- json_response=json_response,
1229
- stateless=stateless,
1230
- session_timeout=session_timeout,
1231
- )
1232
-
1233
- auth_note = "api-key required" if api_key else "no auth (set --api-key to require one)"
1234
- print(
1235
- f"graphify MCP server (streamable-http) on http://{host}:{port}{path} - {auth_note}",
1236
- file=sys.stderr,
1237
- )
1238
- if host in ("0.0.0.0", "::", "") and not api_key:
1239
- print(
1240
- f"WARNING: binding {host or '0.0.0.0'} with no api-key exposes the graph "
1241
- "unauthenticated on the network. Set --api-key (or GRAPHIFY_API_KEY).",
1242
- file=sys.stderr,
1243
- )
1244
- uvicorn.run(app, host=host, port=port)
1245
-
1246
-
1247
- def _main(argv: list[str] | None = None) -> None:
1248
- import argparse
1249
- import os
1250
-
1251
- parser = argparse.ArgumentParser(
1252
- prog="python -m graphify.serve",
1253
- description="Serve a graphify knowledge graph over MCP (stdio or Streamable HTTP).",
1254
- )
1255
- parser.add_argument(
1256
- "graph_path",
1257
- nargs="?",
1258
- default="graphify-out/graph.json",
1259
- help="Path to graph.json (default: graphify-out/graph.json)",
1260
- )
1261
- parser.add_argument(
1262
- "--transport",
1263
- choices=["stdio", "http"],
1264
- default="stdio",
1265
- help="Transport to serve on (default: stdio)",
1266
- )
1267
- parser.add_argument("--host", default="127.0.0.1", help="HTTP bind host (default: 127.0.0.1)")
1268
- parser.add_argument("--port", type=int, default=8080, help="HTTP bind port (default: 8080)")
1269
- parser.add_argument(
1270
- "--api-key",
1271
- default=os.environ.get("GRAPHIFY_API_KEY"),
1272
- help="Require this key on the HTTP transport (env: GRAPHIFY_API_KEY)",
1273
- )
1274
- parser.add_argument("--path", default="/mcp", help="HTTP mount path (default: /mcp)")
1275
- parser.add_argument(
1276
- "--json-response",
1277
- action="store_true",
1278
- help="Return plain JSON responses instead of SSE streams",
1279
- )
1280
- parser.add_argument(
1281
- "--stateless",
1282
- action="store_true",
1283
- help="Run without per-session state (for load-balanced / CI deployments)",
1284
- )
1285
- parser.add_argument(
1286
- "--session-timeout",
1287
- type=float,
1288
- default=3600.0,
1289
- help="Reap stateful sessions idle this many seconds (default: 3600; 0 disables)",
1290
- )
1291
- args = parser.parse_args(argv)
1292
-
1293
- if args.transport == "http":
1294
- serve_http(
1295
- args.graph_path,
1296
- host=args.host,
1297
- port=args.port,
1298
- api_key=args.api_key,
1299
- path=args.path,
1300
- json_response=args.json_response,
1301
- stateless=args.stateless,
1302
- session_timeout=args.session_timeout,
1303
- )
1304
- else:
1305
- serve(args.graph_path)
1306
-
1307
-
1308
- if __name__ == "__main__":
1309
- _main()