@oriro/orirocli 0.1.8 → 0.1.11

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 (1445) hide show
  1. package/ATTRIBUTION.md +53 -45
  2. package/LICENSE +21 -0
  3. package/README.md +20 -17
  4. package/dist/cli.js +4425 -2975
  5. package/package.json +64 -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 -0
  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/graphify/SKILL.md +619 -0
  757. package/skills/graphify/__init__.py +28 -0
  758. package/skills/graphify/__main__.py +4582 -0
  759. package/skills/graphify/affected.py +154 -0
  760. package/skills/graphify/always_on/agents-md.md +12 -0
  761. package/skills/graphify/always_on/antigravity-rules.md +14 -0
  762. package/skills/graphify/always_on/claude-md.md +9 -0
  763. package/skills/graphify/always_on/gemini-md.md +9 -0
  764. package/skills/graphify/always_on/kiro-steering.md +5 -0
  765. package/skills/graphify/always_on/vscode-instructions.md +17 -0
  766. package/skills/graphify/analyze.py +724 -0
  767. package/skills/graphify/benchmark.py +155 -0
  768. package/skills/graphify/build.py +487 -0
  769. package/skills/graphify/cache.py +417 -0
  770. package/skills/graphify/callflow_html.py +2020 -0
  771. package/skills/graphify/cluster.py +272 -0
  772. package/skills/graphify/command-kilo.md +15 -0
  773. package/skills/graphify/dedup.py +429 -0
  774. package/skills/graphify/detect.py +1379 -0
  775. package/skills/graphify/diagnostics.py +390 -0
  776. package/skills/graphify/export.py +1408 -0
  777. package/skills/graphify/extract.py +11570 -0
  778. package/skills/graphify/global_graph.py +159 -0
  779. package/skills/graphify/google_workspace.py +223 -0
  780. package/skills/graphify/hooks.py +457 -0
  781. package/skills/graphify/ingest.py +331 -0
  782. package/skills/graphify/llm.py +1896 -0
  783. package/skills/graphify/manifest.py +4 -0
  784. package/skills/graphify/mcp_ingest.py +392 -0
  785. package/skills/graphify/multigraph_compat.py +212 -0
  786. package/skills/graphify/pg_introspect.py +142 -0
  787. package/skills/graphify/prs.py +748 -0
  788. package/skills/graphify/querylog.py +70 -0
  789. package/skills/graphify/report.py +218 -0
  790. package/skills/graphify/scip_ingest.py +363 -0
  791. package/skills/graphify/security.py +336 -0
  792. package/skills/graphify/semantic_cleanup.py +319 -0
  793. package/skills/graphify/serve.py +1309 -0
  794. package/skills/graphify/skill-aider.md +1246 -0
  795. package/skills/graphify/skill-amp.md +613 -0
  796. package/skills/graphify/skill-claw.md +616 -0
  797. package/skills/graphify/skill-codex.md +613 -0
  798. package/skills/graphify/skill-copilot.md +616 -0
  799. package/skills/graphify/skill-devin.md +1372 -0
  800. package/skills/graphify/skill-droid.md +613 -0
  801. package/skills/graphify/skill-kilo.md +625 -0
  802. package/skills/graphify/skill-kiro.md +615 -0
  803. package/skills/graphify/skill-opencode.md +608 -0
  804. package/skills/graphify/skill-pi.md +615 -0
  805. package/skills/graphify/skill-trae.md +614 -0
  806. package/skills/graphify/skill-vscode.md +612 -0
  807. package/skills/graphify/skill-windows.md +651 -0
  808. package/skills/graphify/skills/amp/references/add-watch.md +56 -0
  809. package/skills/graphify/skills/amp/references/exports.md +71 -0
  810. package/skills/graphify/skills/amp/references/extraction-spec.md +68 -0
  811. package/skills/graphify/skills/amp/references/github-and-merge.md +46 -0
  812. package/skills/graphify/skills/amp/references/hooks.md +33 -0
  813. package/skills/graphify/skills/amp/references/query.md +249 -0
  814. package/skills/graphify/skills/amp/references/transcribe.md +48 -0
  815. package/skills/graphify/skills/amp/references/update.md +179 -0
  816. package/skills/graphify/skills/claude/references/add-watch.md +56 -0
  817. package/skills/graphify/skills/claude/references/exports.md +71 -0
  818. package/skills/graphify/skills/claude/references/extraction-spec.md +68 -0
  819. package/skills/graphify/skills/claude/references/github-and-merge.md +46 -0
  820. package/skills/graphify/skills/claude/references/hooks.md +33 -0
  821. package/skills/graphify/skills/claude/references/query.md +103 -0
  822. package/skills/graphify/skills/claude/references/transcribe.md +48 -0
  823. package/skills/graphify/skills/claude/references/update.md +179 -0
  824. package/skills/graphify/skills/claw/references/add-watch.md +56 -0
  825. package/skills/graphify/skills/claw/references/exports.md +71 -0
  826. package/skills/graphify/skills/claw/references/extraction-spec.md +29 -0
  827. package/skills/graphify/skills/claw/references/github-and-merge.md +46 -0
  828. package/skills/graphify/skills/claw/references/hooks.md +33 -0
  829. package/skills/graphify/skills/claw/references/query.md +249 -0
  830. package/skills/graphify/skills/claw/references/transcribe.md +48 -0
  831. package/skills/graphify/skills/claw/references/update.md +179 -0
  832. package/skills/graphify/skills/codex/references/add-watch.md +56 -0
  833. package/skills/graphify/skills/codex/references/exports.md +71 -0
  834. package/skills/graphify/skills/codex/references/extraction-spec.md +29 -0
  835. package/skills/graphify/skills/codex/references/github-and-merge.md +46 -0
  836. package/skills/graphify/skills/codex/references/hooks.md +33 -0
  837. package/skills/graphify/skills/codex/references/query.md +249 -0
  838. package/skills/graphify/skills/codex/references/transcribe.md +48 -0
  839. package/skills/graphify/skills/codex/references/update.md +179 -0
  840. package/skills/graphify/skills/copilot/references/add-watch.md +56 -0
  841. package/skills/graphify/skills/copilot/references/exports.md +71 -0
  842. package/skills/graphify/skills/copilot/references/extraction-spec.md +68 -0
  843. package/skills/graphify/skills/copilot/references/github-and-merge.md +46 -0
  844. package/skills/graphify/skills/copilot/references/hooks.md +33 -0
  845. package/skills/graphify/skills/copilot/references/query.md +249 -0
  846. package/skills/graphify/skills/copilot/references/transcribe.md +48 -0
  847. package/skills/graphify/skills/copilot/references/update.md +179 -0
  848. package/skills/graphify/skills/droid/references/add-watch.md +56 -0
  849. package/skills/graphify/skills/droid/references/exports.md +71 -0
  850. package/skills/graphify/skills/droid/references/extraction-spec.md +68 -0
  851. package/skills/graphify/skills/droid/references/github-and-merge.md +46 -0
  852. package/skills/graphify/skills/droid/references/hooks.md +33 -0
  853. package/skills/graphify/skills/droid/references/query.md +249 -0
  854. package/skills/graphify/skills/droid/references/transcribe.md +48 -0
  855. package/skills/graphify/skills/droid/references/update.md +179 -0
  856. package/skills/graphify/skills/kilo/references/add-watch.md +56 -0
  857. package/skills/graphify/skills/kilo/references/exports.md +71 -0
  858. package/skills/graphify/skills/kilo/references/extraction-spec.md +68 -0
  859. package/skills/graphify/skills/kilo/references/github-and-merge.md +46 -0
  860. package/skills/graphify/skills/kilo/references/hooks.md +33 -0
  861. package/skills/graphify/skills/kilo/references/query.md +249 -0
  862. package/skills/graphify/skills/kilo/references/transcribe.md +48 -0
  863. package/skills/graphify/skills/kilo/references/update.md +179 -0
  864. package/skills/graphify/skills/kiro/references/add-watch.md +56 -0
  865. package/skills/graphify/skills/kiro/references/exports.md +71 -0
  866. package/skills/graphify/skills/kiro/references/extraction-spec.md +29 -0
  867. package/skills/graphify/skills/kiro/references/github-and-merge.md +46 -0
  868. package/skills/graphify/skills/kiro/references/hooks.md +33 -0
  869. package/skills/graphify/skills/kiro/references/query.md +249 -0
  870. package/skills/graphify/skills/kiro/references/transcribe.md +48 -0
  871. package/skills/graphify/skills/kiro/references/update.md +179 -0
  872. package/skills/graphify/skills/opencode/references/add-watch.md +56 -0
  873. package/skills/graphify/skills/opencode/references/exports.md +71 -0
  874. package/skills/graphify/skills/opencode/references/extraction-spec.md +68 -0
  875. package/skills/graphify/skills/opencode/references/github-and-merge.md +46 -0
  876. package/skills/graphify/skills/opencode/references/hooks.md +33 -0
  877. package/skills/graphify/skills/opencode/references/query.md +249 -0
  878. package/skills/graphify/skills/opencode/references/transcribe.md +48 -0
  879. package/skills/graphify/skills/opencode/references/update.md +179 -0
  880. package/skills/graphify/skills/pi/references/add-watch.md +56 -0
  881. package/skills/graphify/skills/pi/references/exports.md +71 -0
  882. package/skills/graphify/skills/pi/references/extraction-spec.md +29 -0
  883. package/skills/graphify/skills/pi/references/github-and-merge.md +46 -0
  884. package/skills/graphify/skills/pi/references/hooks.md +33 -0
  885. package/skills/graphify/skills/pi/references/query.md +249 -0
  886. package/skills/graphify/skills/pi/references/transcribe.md +48 -0
  887. package/skills/graphify/skills/pi/references/update.md +179 -0
  888. package/skills/graphify/skills/trae/references/add-watch.md +56 -0
  889. package/skills/graphify/skills/trae/references/exports.md +71 -0
  890. package/skills/graphify/skills/trae/references/extraction-spec.md +68 -0
  891. package/skills/graphify/skills/trae/references/github-and-merge.md +46 -0
  892. package/skills/graphify/skills/trae/references/hooks.md +35 -0
  893. package/skills/graphify/skills/trae/references/query.md +249 -0
  894. package/skills/graphify/skills/trae/references/transcribe.md +48 -0
  895. package/skills/graphify/skills/trae/references/update.md +179 -0
  896. package/skills/graphify/skills/vscode/references/add-watch.md +56 -0
  897. package/skills/graphify/skills/vscode/references/exports.md +71 -0
  898. package/skills/graphify/skills/vscode/references/extraction-spec.md +68 -0
  899. package/skills/graphify/skills/vscode/references/github-and-merge.md +46 -0
  900. package/skills/graphify/skills/vscode/references/hooks.md +33 -0
  901. package/skills/graphify/skills/vscode/references/query.md +249 -0
  902. package/skills/graphify/skills/vscode/references/transcribe.md +48 -0
  903. package/skills/graphify/skills/vscode/references/update.md +179 -0
  904. package/skills/graphify/skills/windows/references/add-watch.md +56 -0
  905. package/skills/graphify/skills/windows/references/exports.md +71 -0
  906. package/skills/graphify/skills/windows/references/extraction-spec.md +68 -0
  907. package/skills/graphify/skills/windows/references/github-and-merge.md +46 -0
  908. package/skills/graphify/skills/windows/references/hooks.md +33 -0
  909. package/skills/graphify/skills/windows/references/query.md +249 -0
  910. package/skills/graphify/skills/windows/references/transcribe.md +48 -0
  911. package/skills/graphify/skills/windows/references/update.md +179 -0
  912. package/skills/graphify/symbol_resolution.py +538 -0
  913. package/skills/graphify/transcribe.py +184 -0
  914. package/skills/graphify/tree_html.py +582 -0
  915. package/skills/graphify/validate.py +72 -0
  916. package/skills/graphify/watch.py +898 -0
  917. package/skills/graphify/wiki.py +282 -0
  918. package/skills/health/health-aging/LICENSE +21 -21
  919. package/skills/health/health-aging/SKILL.md +82 -82
  920. package/skills/health/health-chronic/LICENSE +21 -21
  921. package/skills/health/health-chronic/SKILL.md +202 -202
  922. package/skills/health/health-dental/LICENSE +21 -21
  923. package/skills/health/health-dental/SKILL.md +41 -41
  924. package/skills/health/health-eye-care/LICENSE +21 -21
  925. package/skills/health/health-eye-care/SKILL.md +56 -56
  926. package/skills/health/health-first-aid/LICENSE +21 -21
  927. package/skills/health/health-first-aid/SKILL.md +201 -201
  928. package/skills/health/health-fitness/LICENSE +21 -21
  929. package/skills/health/health-fitness/SKILL.md +111 -111
  930. package/skills/health/health-general/LICENSE +21 -21
  931. package/skills/health/health-general/SKILL.md +277 -277
  932. package/skills/health/health-mens/LICENSE +21 -21
  933. package/skills/health/health-mens/SKILL.md +53 -53
  934. package/skills/health/health-mental/LICENSE +21 -21
  935. package/skills/health/health-mental/SKILL.md +221 -221
  936. package/skills/health/health-naturopathy-ayurveda/LICENSE +21 -21
  937. package/skills/health/health-naturopathy-ayurveda/SKILL.md +60 -60
  938. package/skills/health/health-nutrition/LICENSE +21 -21
  939. package/skills/health/health-nutrition/SKILL.md +262 -262
  940. package/skills/health/health-pediatric/LICENSE +21 -21
  941. package/skills/health/health-pediatric/SKILL.md +94 -94
  942. package/skills/health/health-pharmacology/LICENSE +21 -21
  943. package/skills/health/health-pharmacology/SKILL.md +87 -87
  944. package/skills/health/health-pregnancy/LICENSE +21 -21
  945. package/skills/health/health-pregnancy/SKILL.md +71 -71
  946. package/skills/health/health-skin/LICENSE +21 -21
  947. package/skills/health/health-skin/SKILL.md +71 -71
  948. package/skills/health/health-sleep/LICENSE +21 -21
  949. package/skills/health/health-sleep/SKILL.md +81 -81
  950. package/skills/health/health-womens/LICENSE +21 -21
  951. package/skills/health/health-womens/SKILL.md +72 -72
  952. package/skills/health/health-yoga-wellness/LICENSE +21 -21
  953. package/skills/health/health-yoga-wellness/SKILL.md +58 -58
  954. package/skills/healthcare-systems/health-sys-global/LICENSE +21 -21
  955. package/skills/healthcare-systems/health-sys-global/SKILL.md +69 -69
  956. package/skills/healthcare-systems/health-sys-management/LICENSE +21 -21
  957. package/skills/healthcare-systems/health-sys-management/SKILL.md +71 -71
  958. package/skills/healthcare-systems/health-sys-navigation/LICENSE +21 -21
  959. package/skills/healthcare-systems/health-sys-navigation/SKILL.md +60 -60
  960. package/skills/healthcare-systems/health-sys-public/LICENSE +21 -21
  961. package/skills/healthcare-systems/health-sys-public/SKILL.md +71 -71
  962. package/skills/healthcheck/SKILL.md +109 -109
  963. package/skills/himalaya/SKILL.md +84 -84
  964. package/skills/himalaya/references/configuration.md +184 -184
  965. package/skills/himalaya/references/message-composition.md +199 -199
  966. package/skills/humanities/humanities-history-world/LICENSE +21 -21
  967. package/skills/humanities/humanities-history-world/SKILL.md +59 -59
  968. package/skills/humanities/humanities-indian-classical/LICENSE +21 -21
  969. package/skills/humanities/humanities-indian-classical/SKILL.md +104 -104
  970. package/skills/humanities/humanities-philosophy/LICENSE +21 -21
  971. package/skills/humanities/humanities-philosophy/SKILL.md +105 -105
  972. package/skills/humanities/humanities-world-religions/LICENSE +21 -21
  973. package/skills/humanities/humanities-world-religions/SKILL.md +67 -67
  974. package/skills/impeccable/SKILL.md +186 -0
  975. package/skills/impeccable/agents/impeccable_asset_producer.toml +92 -0
  976. package/skills/impeccable/agents/impeccable_manual_edit_applier.toml +95 -0
  977. package/skills/impeccable/agents/openai.yaml +4 -0
  978. package/skills/impeccable/reference/adapt.md +311 -0
  979. package/skills/impeccable/reference/animate.md +201 -0
  980. package/skills/impeccable/reference/audit.md +133 -0
  981. package/skills/impeccable/reference/bolder.md +113 -0
  982. package/skills/impeccable/reference/brand.md +108 -0
  983. package/skills/impeccable/reference/clarify.md +288 -0
  984. package/skills/impeccable/reference/codex.md +105 -0
  985. package/skills/impeccable/reference/colorize.md +257 -0
  986. package/skills/impeccable/reference/craft.md +123 -0
  987. package/skills/impeccable/reference/critique.md +790 -0
  988. package/skills/impeccable/reference/delight.md +302 -0
  989. package/skills/impeccable/reference/distill.md +111 -0
  990. package/skills/impeccable/reference/document.md +429 -0
  991. package/skills/impeccable/reference/extract.md +69 -0
  992. package/skills/impeccable/reference/harden.md +347 -0
  993. package/skills/impeccable/reference/init.md +172 -0
  994. package/skills/impeccable/reference/interaction-design.md +189 -0
  995. package/skills/impeccable/reference/layout.md +161 -0
  996. package/skills/impeccable/reference/live.md +720 -0
  997. package/skills/impeccable/reference/onboard.md +234 -0
  998. package/skills/impeccable/reference/optimize.md +258 -0
  999. package/skills/impeccable/reference/overdrive.md +130 -0
  1000. package/skills/impeccable/reference/polish.md +241 -0
  1001. package/skills/impeccable/reference/product.md +60 -0
  1002. package/skills/impeccable/reference/quieter.md +99 -0
  1003. package/skills/impeccable/reference/shape.md +165 -0
  1004. package/skills/impeccable/reference/typeset.md +279 -0
  1005. package/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  1006. package/skills/impeccable/scripts/command-metadata.json +94 -0
  1007. package/skills/impeccable/scripts/context-signals.mjs +225 -0
  1008. package/skills/impeccable/scripts/context.mjs +266 -0
  1009. package/skills/impeccable/scripts/critique-storage.mjs +242 -0
  1010. package/skills/impeccable/scripts/design-parser.mjs +835 -0
  1011. package/skills/impeccable/scripts/detect-csp.mjs +198 -0
  1012. package/skills/impeccable/scripts/detect.mjs +21 -0
  1013. package/skills/impeccable/scripts/detector/browser/injected/index.mjs +1733 -0
  1014. package/skills/impeccable/scripts/detector/cli/main.mjs +244 -0
  1015. package/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +4618 -0
  1016. package/skills/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
  1017. package/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
  1018. package/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
  1019. package/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
  1020. package/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
  1021. package/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
  1022. package/skills/impeccable/scripts/detector/findings.mjs +12 -0
  1023. package/skills/impeccable/scripts/detector/node/file-system.mjs +198 -0
  1024. package/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
  1025. package/skills/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
  1026. package/skills/impeccable/scripts/detector/rules/checks.mjs +2384 -0
  1027. package/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
  1028. package/skills/impeccable/scripts/detector/shared/constants.mjs +101 -0
  1029. package/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
  1030. package/skills/impeccable/scripts/impeccable-paths.mjs +126 -0
  1031. package/skills/impeccable/scripts/is-generated.mjs +69 -0
  1032. package/skills/impeccable/scripts/live-accept.mjs +812 -0
  1033. package/skills/impeccable/scripts/live-browser-session.js +123 -0
  1034. package/skills/impeccable/scripts/live-browser.js +10295 -0
  1035. package/skills/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
  1036. package/skills/impeccable/scripts/live-complete.mjs +75 -0
  1037. package/skills/impeccable/scripts/live-completion.mjs +19 -0
  1038. package/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
  1039. package/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
  1040. package/skills/impeccable/scripts/live-event-validation.mjs +137 -0
  1041. package/skills/impeccable/scripts/live-inject.mjs +557 -0
  1042. package/skills/impeccable/scripts/live-insert-ui.mjs +458 -0
  1043. package/skills/impeccable/scripts/live-insert.mjs +272 -0
  1044. package/skills/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
  1045. package/skills/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
  1046. package/skills/impeccable/scripts/live-poll.mjs +379 -0
  1047. package/skills/impeccable/scripts/live-resume.mjs +94 -0
  1048. package/skills/impeccable/scripts/live-server.mjs +2326 -0
  1049. package/skills/impeccable/scripts/live-session-store.mjs +289 -0
  1050. package/skills/impeccable/scripts/live-status.mjs +61 -0
  1051. package/skills/impeccable/scripts/live-svelte-component.mjs +826 -0
  1052. package/skills/impeccable/scripts/live-sveltekit-adapter.mjs +274 -0
  1053. package/skills/impeccable/scripts/live-ui-core.mjs +179 -0
  1054. package/skills/impeccable/scripts/live-vocabulary.mjs +36 -0
  1055. package/skills/impeccable/scripts/live-wrap.mjs +894 -0
  1056. package/skills/impeccable/scripts/live.mjs +246 -0
  1057. package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  1058. package/skills/impeccable/scripts/palette.mjs +633 -0
  1059. package/skills/impeccable/scripts/pin.mjs +214 -0
  1060. package/skills/imsg/SKILL.md +126 -126
  1061. package/skills/industry/industry-construction/LICENSE +21 -21
  1062. package/skills/industry/industry-construction/SKILL.md +81 -81
  1063. package/skills/industry/industry-education-sector/LICENSE +21 -21
  1064. package/skills/industry/industry-education-sector/SKILL.md +49 -49
  1065. package/skills/industry/industry-fashion/LICENSE +21 -21
  1066. package/skills/industry/industry-fashion/SKILL.md +82 -82
  1067. package/skills/industry/industry-food/LICENSE +21 -21
  1068. package/skills/industry/industry-food/SKILL.md +79 -79
  1069. package/skills/industry/industry-government/LICENSE +21 -21
  1070. package/skills/industry/industry-government/SKILL.md +80 -80
  1071. package/skills/industry/industry-hospitality/LICENSE +21 -21
  1072. package/skills/industry/industry-hospitality/SKILL.md +73 -73
  1073. package/skills/industry/industry-insurance-sector/LICENSE +21 -21
  1074. package/skills/industry/industry-insurance-sector/SKILL.md +57 -57
  1075. package/skills/industry/industry-logistics/LICENSE +21 -21
  1076. package/skills/industry/industry-logistics/SKILL.md +80 -80
  1077. package/skills/industry/industry-media/LICENSE +21 -21
  1078. package/skills/industry/industry-media/SKILL.md +66 -66
  1079. package/skills/industry/industry-nonprofit/LICENSE +21 -21
  1080. package/skills/industry/industry-nonprofit/SKILL.md +77 -77
  1081. package/skills/industry/industry-pharma/LICENSE +21 -21
  1082. package/skills/industry/industry-pharma/SKILL.md +69 -69
  1083. package/skills/industry/industry-real-estate/LICENSE +21 -21
  1084. package/skills/industry/industry-real-estate/SKILL.md +61 -61
  1085. package/skills/industry/industry-sports/LICENSE +21 -21
  1086. package/skills/industry/industry-sports/SKILL.md +71 -71
  1087. package/skills/industry/industry-tech-startup/LICENSE +21 -21
  1088. package/skills/industry/industry-tech-startup/SKILL.md +82 -82
  1089. package/skills/internal-comms/LICENSE +21 -21
  1090. package/skills/internal-comms/SKILL.md +38 -38
  1091. package/skills/internal-comms/examples/3p-updates.md +49 -49
  1092. package/skills/internal-comms/examples/company-newsletter.md +76 -76
  1093. package/skills/internal-comms/examples/faq-answers.md +35 -35
  1094. package/skills/internal-comms/examples/general-comms.md +19 -19
  1095. package/skills/legal/legal-business/LICENSE +21 -21
  1096. package/skills/legal/legal-business/SKILL.md +227 -227
  1097. package/skills/legal/legal-consumer/LICENSE +21 -21
  1098. package/skills/legal/legal-consumer/SKILL.md +155 -155
  1099. package/skills/legal/legal-contracts/LICENSE +21 -21
  1100. package/skills/legal/legal-contracts/SKILL.md +268 -268
  1101. package/skills/legal/legal-corporate-governance/LICENSE +21 -21
  1102. package/skills/legal/legal-corporate-governance/SKILL.md +53 -53
  1103. package/skills/legal/legal-employment/LICENSE +21 -21
  1104. package/skills/legal/legal-employment/SKILL.md +291 -291
  1105. package/skills/legal/legal-immigration/LICENSE +21 -21
  1106. package/skills/legal/legal-immigration/SKILL.md +146 -146
  1107. package/skills/legal/legal-international/LICENSE +21 -21
  1108. package/skills/legal/legal-international/SKILL.md +51 -51
  1109. package/skills/legal/legal-ip/LICENSE +21 -21
  1110. package/skills/legal/legal-ip/SKILL.md +264 -264
  1111. package/skills/legal/legal-privacy/LICENSE +21 -21
  1112. package/skills/legal/legal-privacy/SKILL.md +161 -161
  1113. package/skills/legal/legal-real-estate/LICENSE +21 -21
  1114. package/skills/legal/legal-real-estate/SKILL.md +142 -142
  1115. package/skills/legal/legal-startup/LICENSE +21 -21
  1116. package/skills/legal/legal-startup/SKILL.md +182 -182
  1117. package/skills/legal/legal-tax/LICENSE +21 -21
  1118. package/skills/legal/legal-tax/SKILL.md +156 -156
  1119. package/skills/mcp-builder/LICENSE +21 -21
  1120. package/skills/mcp-builder/SKILL.md +257 -257
  1121. package/skills/mcp-builder/reference/evaluation.md +630 -630
  1122. package/skills/mcp-builder/reference/mcp_best_practices.md +269 -269
  1123. package/skills/mcp-builder/reference/node_mcp_server.md +980 -980
  1124. package/skills/mcp-builder/reference/python_mcp_server.md +737 -737
  1125. package/skills/mcp-builder/scripts/connections.py +151 -151
  1126. package/skills/mcp-builder/scripts/evaluation.py +373 -373
  1127. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
  1128. package/skills/mcp-builder/scripts/requirements.txt +2 -2
  1129. package/skills/mcporter/SKILL.md +65 -65
  1130. package/skills/meme-maker/SKILL.md +46 -46
  1131. package/skills/meme-maker/references/templates.json +358 -358
  1132. package/skills/meme-maker/scripts/meme.mjs +398 -398
  1133. package/skills/mental-health/mental-health-cbt/LICENSE +21 -21
  1134. package/skills/mental-health/mental-health-cbt/SKILL.md +254 -254
  1135. package/skills/mental-health/psych-addiction/LICENSE +21 -21
  1136. package/skills/mental-health/psych-addiction/SKILL.md +79 -79
  1137. package/skills/mental-health/psych-behavioral-econ/LICENSE +21 -21
  1138. package/skills/mental-health/psych-behavioral-econ/SKILL.md +84 -84
  1139. package/skills/mental-health/psych-child/LICENSE +21 -21
  1140. package/skills/mental-health/psych-child/SKILL.md +84 -84
  1141. package/skills/mental-health/psych-grief/LICENSE +21 -21
  1142. package/skills/mental-health/psych-grief/SKILL.md +85 -85
  1143. package/skills/mental-health/psych-mindfulness/LICENSE +21 -21
  1144. package/skills/mental-health/psych-mindfulness/SKILL.md +71 -71
  1145. package/skills/mental-health/psych-org/LICENSE +21 -21
  1146. package/skills/mental-health/psych-org/SKILL.md +115 -115
  1147. package/skills/mental-health/psych-positive/LICENSE +21 -21
  1148. package/skills/mental-health/psych-positive/SKILL.md +86 -86
  1149. package/skills/mental-health/psych-relationships/LICENSE +21 -21
  1150. package/skills/mental-health/psych-relationships/SKILL.md +100 -100
  1151. package/skills/mental-health/psych-trauma/LICENSE +21 -21
  1152. package/skills/mental-health/psych-trauma/SKILL.md +109 -109
  1153. package/skills/model-usage/SKILL.md +75 -75
  1154. package/skills/model-usage/references/codexbar-cli.md +33 -33
  1155. package/skills/model-usage/scripts/model_usage.py +319 -319
  1156. package/skills/model-usage/scripts/test_model_usage.py +40 -40
  1157. package/skills/nano-pdf/SKILL.md +42 -42
  1158. package/skills/node-connect/SKILL.md +147 -147
  1159. package/skills/node-inspect-debugger/SKILL.md +88 -88
  1160. package/skills/notion/SKILL.md +154 -154
  1161. package/skills/obsidian/SKILL.md +123 -123
  1162. package/skills/openai-whisper/SKILL.md +42 -42
  1163. package/skills/openai-whisper-api/SKILL.md +75 -75
  1164. package/skills/openai-whisper-api/scripts/transcribe.sh +154 -154
  1165. package/skills/openhue/SKILL.md +116 -116
  1166. package/skills/oracle/SKILL.md +130 -130
  1167. package/skills/ordercli/SKILL.md +82 -82
  1168. package/skills/peekaboo/SKILL.md +217 -217
  1169. package/skills/pyproject.toml +10 -10
  1170. package/skills/python-debugpy/SKILL.md +76 -76
  1171. package/skills/sag/SKILL.md +91 -91
  1172. package/skills/science/sci-astronomy/LICENSE +21 -21
  1173. package/skills/science/sci-astronomy/SKILL.md +80 -80
  1174. package/skills/science/sci-biology/LICENSE +21 -21
  1175. package/skills/science/sci-biology/SKILL.md +74 -74
  1176. package/skills/science/sci-chemistry/LICENSE +21 -21
  1177. package/skills/science/sci-chemistry/SKILL.md +89 -89
  1178. package/skills/science/sci-climate/LICENSE +21 -21
  1179. package/skills/science/sci-climate/SKILL.md +72 -72
  1180. package/skills/science/sci-data-analysis/LICENSE +21 -21
  1181. package/skills/science/sci-data-analysis/SKILL.md +87 -87
  1182. package/skills/science/sci-environmental-science/LICENSE +21 -21
  1183. package/skills/science/sci-environmental-science/SKILL.md +69 -69
  1184. package/skills/science/sci-geology/LICENSE +21 -21
  1185. package/skills/science/sci-geology/SKILL.md +56 -56
  1186. package/skills/science/sci-method/LICENSE +21 -21
  1187. package/skills/science/sci-method/SKILL.md +77 -77
  1188. package/skills/science/sci-neuroscience/LICENSE +21 -21
  1189. package/skills/science/sci-neuroscience/SKILL.md +79 -79
  1190. package/skills/science/sci-physics/LICENSE +21 -21
  1191. package/skills/science/sci-physics/SKILL.md +78 -78
  1192. package/skills/science/sci-research-methods/LICENSE +21 -21
  1193. package/skills/science/sci-research-methods/SKILL.md +83 -83
  1194. package/skills/science/sci-statistics/LICENSE +21 -21
  1195. package/skills/science/sci-statistics/SKILL.md +249 -249
  1196. package/skills/session-logs/SKILL.md +155 -155
  1197. package/skills/sherpa-onnx-tts/SKILL.md +113 -113
  1198. package/skills/skill-creator/SKILL.md +81 -81
  1199. package/skills/skill-creator/license.txt +202 -202
  1200. package/skills/skill-creator/scripts/init_skill.py +378 -378
  1201. package/skills/skill-creator/scripts/package_skill.py +144 -144
  1202. package/skills/skill-creator/scripts/quick_validate.py +169 -169
  1203. package/skills/skill-creator/scripts/test_init_skill.py +51 -51
  1204. package/skills/skill-creator/scripts/test_package_skill.py +199 -199
  1205. package/skills/skill-creator/scripts/test_quick_validate.py +116 -116
  1206. package/skills/slack/SKILL.md +82 -82
  1207. package/skills/slack-gif-creator/LICENSE +21 -21
  1208. package/skills/slack-gif-creator/SKILL.md +293 -293
  1209. package/skills/slack-gif-creator/requirements.txt +3 -3
  1210. package/skills/social-sciences/social-anthropology/LICENSE +21 -21
  1211. package/skills/social-sciences/social-anthropology/SKILL.md +62 -62
  1212. package/skills/social-sciences/social-economics/LICENSE +21 -21
  1213. package/skills/social-sciences/social-economics/SKILL.md +88 -88
  1214. package/skills/social-sciences/social-geography/LICENSE +21 -21
  1215. package/skills/social-sciences/social-geography/SKILL.md +61 -61
  1216. package/skills/social-sciences/social-international-dev/LICENSE +21 -21
  1217. package/skills/social-sciences/social-international-dev/SKILL.md +76 -76
  1218. package/skills/social-sciences/social-political-science/LICENSE +21 -21
  1219. package/skills/social-sciences/social-political-science/SKILL.md +70 -70
  1220. package/skills/social-sciences/social-public-policy/LICENSE +21 -21
  1221. package/skills/social-sciences/social-public-policy/SKILL.md +73 -73
  1222. package/skills/social-sciences/social-sociology/LICENSE +21 -21
  1223. package/skills/social-sciences/social-sociology/SKILL.md +78 -78
  1224. package/skills/songsee/SKILL.md +53 -53
  1225. package/skills/sonoscli/SKILL.md +69 -69
  1226. package/skills/spike/SKILL.md +55 -55
  1227. package/skills/spotify-player/SKILL.md +68 -68
  1228. package/skills/summarize/SKILL.md +90 -90
  1229. package/skills/taskflow/SKILL.md +153 -153
  1230. package/skills/taskflow/examples/inbox-triage.lobster +33 -33
  1231. package/skills/taskflow/examples/pr-intake.lobster +32 -32
  1232. package/skills/taskflow-inbox-triage/SKILL.md +123 -123
  1233. package/skills/technical/ai-ethics/LICENSE +21 -21
  1234. package/skills/technical/ai-ethics/SKILL.md +92 -92
  1235. package/skills/technical/ai-product-builder/LICENSE +21 -21
  1236. package/skills/technical/ai-product-builder/SKILL.md +180 -180
  1237. package/skills/technical/analytics-setup/LICENSE +21 -21
  1238. package/skills/technical/analytics-setup/SKILL.md +125 -125
  1239. package/skills/technical/api-builder/LICENSE +21 -21
  1240. package/skills/technical/api-builder/SKILL.md +202 -202
  1241. package/skills/technical/architecture-decisions/LICENSE +21 -21
  1242. package/skills/technical/architecture-decisions/SKILL.md +120 -120
  1243. package/skills/technical/auth-security/LICENSE +21 -21
  1244. package/skills/technical/auth-security/SKILL.md +209 -209
  1245. package/skills/technical/blockchain-web3/LICENSE +21 -21
  1246. package/skills/technical/blockchain-web3/SKILL.md +84 -84
  1247. package/skills/technical/cloud-architecture/LICENSE +21 -21
  1248. package/skills/technical/cloud-architecture/SKILL.md +85 -85
  1249. package/skills/technical/content-platform/LICENSE +21 -21
  1250. package/skills/technical/content-platform/SKILL.md +134 -134
  1251. package/skills/technical/cybersecurity-advanced/LICENSE +21 -21
  1252. package/skills/technical/cybersecurity-advanced/SKILL.md +99 -99
  1253. package/skills/technical/data-engineering/LICENSE +21 -21
  1254. package/skills/technical/data-engineering/SKILL.md +117 -117
  1255. package/skills/technical/database-design/LICENSE +21 -21
  1256. package/skills/technical/database-design/SKILL.md +185 -185
  1257. package/skills/technical/devops-cicd/LICENSE +21 -21
  1258. package/skills/technical/devops-cicd/SKILL.md +181 -181
  1259. package/skills/technical/ecommerce-builder/LICENSE +21 -21
  1260. package/skills/technical/ecommerce-builder/SKILL.md +123 -123
  1261. package/skills/technical/email-marketing/LICENSE +21 -21
  1262. package/skills/technical/email-marketing/SKILL.md +128 -128
  1263. package/skills/technical/fintech-builder/LICENSE +21 -21
  1264. package/skills/technical/fintech-builder/SKILL.md +141 -141
  1265. package/skills/technical/full-stack-web/LICENSE +21 -21
  1266. package/skills/technical/full-stack-web/SKILL.md +173 -173
  1267. package/skills/technical/gdpr-basics/LICENSE +21 -21
  1268. package/skills/technical/gdpr-basics/SKILL.md +145 -145
  1269. package/skills/technical/launch-playbook/LICENSE +21 -21
  1270. package/skills/technical/launch-playbook/SKILL.md +95 -95
  1271. package/skills/technical/marketing-copy/LICENSE +21 -21
  1272. package/skills/technical/marketing-copy/SKILL.md +126 -126
  1273. package/skills/technical/marketplace-builder/LICENSE +21 -21
  1274. package/skills/technical/marketplace-builder/SKILL.md +105 -105
  1275. package/skills/technical/mobile-pwa/LICENSE +21 -21
  1276. package/skills/technical/mobile-pwa/SKILL.md +191 -191
  1277. package/skills/technical/no-code-tools/LICENSE +21 -21
  1278. package/skills/technical/no-code-tools/SKILL.md +80 -80
  1279. package/skills/technical/open-source/LICENSE +21 -21
  1280. package/skills/technical/open-source/SKILL.md +71 -71
  1281. package/skills/technical/performance-optimization/LICENSE +21 -21
  1282. package/skills/technical/performance-optimization/SKILL.md +155 -155
  1283. package/skills/technical/pricing-design/LICENSE +21 -21
  1284. package/skills/technical/pricing-design/SKILL.md +87 -87
  1285. package/skills/technical/product-management/LICENSE +21 -21
  1286. package/skills/technical/product-management/SKILL.md +94 -94
  1287. package/skills/technical/saas-builder/LICENSE +21 -21
  1288. package/skills/technical/saas-builder/SKILL.md +138 -138
  1289. package/skills/technical/scope-estimation/LICENSE +21 -21
  1290. package/skills/technical/scope-estimation/SKILL.md +99 -99
  1291. package/skills/technical/secrets-management/LICENSE +21 -21
  1292. package/skills/technical/secrets-management/SKILL.md +135 -135
  1293. package/skills/technical/seo-technical/LICENSE +21 -21
  1294. package/skills/technical/seo-technical/SKILL.md +136 -136
  1295. package/skills/technical/technical-writing/LICENSE +21 -21
  1296. package/skills/technical/technical-writing/SKILL.md +149 -149
  1297. package/skills/technical/ux-research-tools/LICENSE +21 -21
  1298. package/skills/technical/ux-research-tools/SKILL.md +54 -54
  1299. package/skills/theme-factory/LICENSE +21 -21
  1300. package/skills/theme-factory/SKILL.md +65 -65
  1301. package/skills/theme-factory/themes/arctic-frost.md +19 -19
  1302. package/skills/theme-factory/themes/botanical-garden.md +19 -19
  1303. package/skills/theme-factory/themes/desert-rose.md +19 -19
  1304. package/skills/theme-factory/themes/forest-canopy.md +19 -19
  1305. package/skills/theme-factory/themes/golden-hour.md +19 -19
  1306. package/skills/theme-factory/themes/midnight-galaxy.md +19 -19
  1307. package/skills/theme-factory/themes/modern-minimalist.md +19 -19
  1308. package/skills/theme-factory/themes/ocean-depths.md +19 -19
  1309. package/skills/theme-factory/themes/sunset-boulevard.md +19 -19
  1310. package/skills/theme-factory/themes/tech-innovation.md +19 -19
  1311. package/skills/things-mac/SKILL.md +90 -90
  1312. package/skills/tmux/SKILL.md +95 -95
  1313. package/skills/tmux/scripts/find-sessions.sh +112 -112
  1314. package/skills/tmux/scripts/wait-for-text.sh +83 -83
  1315. package/skills/trades/trades-agriculture/LICENSE +21 -21
  1316. package/skills/trades/trades-agriculture/SKILL.md +80 -80
  1317. package/skills/trades/trades-automotive/LICENSE +21 -21
  1318. package/skills/trades/trades-automotive/SKILL.md +84 -84
  1319. package/skills/trades/trades-carpentry/LICENSE +21 -21
  1320. package/skills/trades/trades-carpentry/SKILL.md +71 -71
  1321. package/skills/trades/trades-cooking-pro/LICENSE +21 -21
  1322. package/skills/trades/trades-cooking-pro/SKILL.md +90 -90
  1323. package/skills/trades/trades-electrical/LICENSE +21 -21
  1324. package/skills/trades/trades-electrical/SKILL.md +146 -146
  1325. package/skills/trades/trades-hvac/LICENSE +21 -21
  1326. package/skills/trades/trades-hvac/SKILL.md +80 -80
  1327. package/skills/trades/trades-landscaping/LICENSE +21 -21
  1328. package/skills/trades/trades-landscaping/SKILL.md +60 -60
  1329. package/skills/trades/trades-metalworking/LICENSE +21 -21
  1330. package/skills/trades/trades-metalworking/SKILL.md +64 -64
  1331. package/skills/trades/trades-painting/LICENSE +21 -21
  1332. package/skills/trades/trades-painting/SKILL.md +70 -70
  1333. package/skills/trades/trades-plumbing/LICENSE +21 -21
  1334. package/skills/trades/trades-plumbing/SKILL.md +160 -160
  1335. package/skills/trades/trades-welding/LICENSE +21 -21
  1336. package/skills/trades/trades-welding/SKILL.md +82 -82
  1337. package/skills/trello/SKILL.md +112 -112
  1338. package/skills/uipm-ui-styling/LICENSE.txt +202 -0
  1339. package/skills/uipm-ui-styling/SKILL.md +328 -0
  1340. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  1341. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  1342. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  1343. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  1344. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  1345. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  1346. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  1347. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  1348. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  1349. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  1350. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  1351. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  1352. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  1353. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  1354. package/skills/uipm-ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  1355. package/skills/uipm-ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  1356. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  1357. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  1358. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  1359. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  1360. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  1361. package/skills/uipm-ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  1362. package/skills/uipm-ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  1363. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  1364. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  1365. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  1366. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  1367. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  1368. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  1369. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  1370. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  1371. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  1372. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  1373. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  1374. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  1375. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  1376. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  1377. package/skills/uipm-ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  1378. package/skills/uipm-ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  1379. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  1380. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  1381. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  1382. package/skills/uipm-ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  1383. package/skills/uipm-ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  1384. package/skills/uipm-ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  1385. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  1386. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  1387. package/skills/uipm-ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  1388. package/skills/uipm-ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  1389. package/skills/uipm-ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  1390. package/skills/uipm-ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  1391. package/skills/uipm-ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  1392. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  1393. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  1394. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  1395. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  1396. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  1397. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  1398. package/skills/uipm-ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  1399. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  1400. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  1401. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  1402. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  1403. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  1404. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  1405. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  1406. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  1407. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  1408. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  1409. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  1410. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  1411. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  1412. package/skills/uipm-ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  1413. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  1414. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  1415. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  1416. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  1417. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  1418. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  1419. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  1420. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  1421. package/skills/uipm-ui-styling/references/canvas-design-system.md +320 -0
  1422. package/skills/uipm-ui-styling/references/shadcn-accessibility.md +471 -0
  1423. package/skills/uipm-ui-styling/references/shadcn-components.md +424 -0
  1424. package/skills/uipm-ui-styling/references/shadcn-theming.md +373 -0
  1425. package/skills/uipm-ui-styling/references/tailwind-customization.md +483 -0
  1426. package/skills/uipm-ui-styling/references/tailwind-responsive.md +382 -0
  1427. package/skills/uipm-ui-styling/references/tailwind-utilities.md +455 -0
  1428. package/skills/uipm-ui-styling/scripts/.coverage +0 -0
  1429. package/skills/uipm-ui-styling/scripts/requirements.txt +17 -0
  1430. package/skills/uipm-ui-styling/scripts/shadcn_add.py +292 -0
  1431. package/skills/uipm-ui-styling/scripts/tailwind_config_gen.py +456 -0
  1432. package/skills/uipm-ui-styling/scripts/tests/coverage-ui.json +1 -0
  1433. package/skills/uipm-ui-styling/scripts/tests/requirements.txt +3 -0
  1434. package/skills/uipm-ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  1435. package/skills/uipm-ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
  1436. package/skills/video-frames/SKILL.md +50 -50
  1437. package/skills/video-frames/scripts/frame.sh +81 -81
  1438. package/skills/voice-call/SKILL.md +49 -49
  1439. package/skills/wacli/SKILL.md +76 -76
  1440. package/skills/weather/SKILL.md +91 -91
  1441. package/skills/web-artifacts-builder/LICENSE +21 -21
  1442. package/skills/web-artifacts-builder/SKILL.md +82 -82
  1443. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +53 -53
  1444. package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -322
  1445. package/skills/xurl/SKILL.md +124 -124
@@ -0,0 +1,1379 @@
1
+ # file discovery, type classification, and corpus health checks
2
+ from __future__ import annotations
3
+ import fnmatch
4
+ import json
5
+ import os
6
+ import re
7
+ import shlex
8
+ from enum import Enum
9
+ from pathlib import Path
10
+
11
+ from graphify.google_workspace import (
12
+ GOOGLE_WORKSPACE_EXTENSIONS,
13
+ convert_google_workspace_file,
14
+ google_workspace_enabled,
15
+ )
16
+
17
+
18
+ class FileType(str, Enum):
19
+ CODE = "code"
20
+ DOCUMENT = "document"
21
+ PAPER = "paper"
22
+ IMAGE = "image"
23
+ VIDEO = "video"
24
+
25
+
26
+ _MANIFEST_PATH = "graphify-out/manifest.json"
27
+
28
+ CODE_EXTENSIONS = {'.py', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.ejs', '.ets', '.go', '.rs', '.java', '.groovy', '.gradle', '.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.rb', '.swift', '.kt', '.kts', '.cs', '.scala', '.php', '.lua', '.luau', '.toc', '.zig', '.ps1', '.ex', '.exs', '.m', '.mm', '.jl', '.vue', '.svelte', '.astro', '.dart', '.v', '.sv', '.svh', '.sql', '.r', '.f', '.F', '.f90', '.F90', '.f95', '.F95', '.f03', '.F03', '.f08', '.F08', '.pas', '.pp', '.dpr', '.dpk', '.lpr', '.inc', '.dfm', '.lfm', '.lpk', '.sh', '.bash', '.json', '.tf', '.tfvars', '.hcl', '.dm', '.dme', '.dmi', '.dmm', '.dmf', '.sln', '.csproj', '.fsproj', '.vbproj', '.razor', '.cshtml', '.cls', '.trigger'}
29
+ DOC_EXTENSIONS = {'.md', '.mdx', '.qmd', '.txt', '.rst', '.html', '.yaml', '.yml'}
30
+ PAPER_EXTENSIONS = {'.pdf'}
31
+ IMAGE_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'}
32
+ OFFICE_EXTENSIONS = {'.docx', '.xlsx'}
33
+ VIDEO_EXTENSIONS = {'.mp4', '.mov', '.webm', '.mkv', '.avi', '.m4v', '.mp3', '.wav', '.m4a', '.ogg'}
34
+
35
+ CORPUS_WARN_THRESHOLD = 50_000 # words - below this, warn "you may not need a graph"
36
+ CORPUS_UPPER_THRESHOLD = 500_000 # words - above this, warn about token cost
37
+ FILE_COUNT_UPPER = 500 # files - above this, warn about token cost
38
+
39
+ # Resource caps for parsing untrusted office/PDF files (F2). A corpus is
40
+ # attacker-controllable (graphify runs on cloned/shared folders), and .docx/.xlsx
41
+ # are zip+XML containers: a few-KB zip-bomb can decompress to gigabytes and
42
+ # OOM-kill the process at load_workbook/Document time. Screen the file before any
43
+ # parser touches it.
44
+ _OFFICE_MAX_RAW_BYTES = 50 * 1024 * 1024 # 50 MiB on-disk
45
+ _OFFICE_MAX_DECOMPRESSED_BYTES = 512 * 1024 * 1024 # 512 MiB total uncompressed
46
+ _OFFICE_MAX_COMPRESSION_RATIO = 200 # uncompressed : compressed
47
+
48
+
49
+ def _file_within_size_cap(path: Path, cap: int = _OFFICE_MAX_RAW_BYTES) -> bool:
50
+ """True if *path* exists and its on-disk size is within *cap*."""
51
+ try:
52
+ return path.stat().st_size <= cap
53
+ except OSError:
54
+ return False
55
+
56
+
57
+ def _zip_within_caps(path: Path) -> bool:
58
+ """Reject a zip-based office file that is a likely zip/XML bomb.
59
+
60
+ Two layers, because the zip central-directory sizes are attacker-controlled:
61
+ 1. A cheap pre-filter on the declared sizes (on-disk cap, summed-uncompressed
62
+ cap, compression ratio) that rejects an honest bomb without decompressing.
63
+ 2. An authoritative pass that stream-decompresses every member with a hard
64
+ byte ceiling, so a member that under-declares its size in the central
65
+ directory cannot expand past the cap undetected. Decompression is chunked
66
+ and bounded, so checking a bomb never materializes more than the ceiling.
67
+ """
68
+ import zipfile
69
+ if not _file_within_size_cap(path):
70
+ return False
71
+ try:
72
+ with zipfile.ZipFile(path) as zf:
73
+ infos = zf.infolist()
74
+ compressed = sum(i.compress_size for i in infos) or 1
75
+ declared = sum(i.file_size for i in infos)
76
+ if declared > _OFFICE_MAX_DECOMPRESSED_BYTES:
77
+ return False
78
+ if declared / compressed > _OFFICE_MAX_COMPRESSION_RATIO:
79
+ return False
80
+ total = 0
81
+ for info in infos:
82
+ with zf.open(info) as member:
83
+ while True:
84
+ chunk = member.read(1024 * 1024)
85
+ if not chunk:
86
+ break
87
+ total += len(chunk)
88
+ if total > _OFFICE_MAX_DECOMPRESSED_BYTES:
89
+ return False
90
+ except (zipfile.BadZipFile, OSError, EOFError):
91
+ return False
92
+ return True
93
+
94
+ # Parent directories whose contents are always sensitive.
95
+ # Checked against path.parts[:-1] (parents only) so a root-level file named
96
+ # "credentials" or "secrets" is not falsely flagged by this stage.
97
+ _SENSITIVE_DIRS = frozenset({
98
+ ".ssh", ".gnupg", ".aws", ".gcloud", "secrets", ".secrets", "credentials",
99
+ })
100
+
101
+ # Files that may contain secrets - skip silently. These patterns are specific
102
+ # (extensions, exact credential-store names) and always apply.
103
+ _SENSITIVE_PATTERNS = [
104
+ re.compile(r'(^|[\\/])\.(env|envrc)(\.|$)', re.IGNORECASE),
105
+ re.compile(r'\.(pem|key|p12|pfx|cert|crt|der|p8)$', re.IGNORECASE),
106
+ re.compile(r'(id_rsa|id_dsa|id_ecdsa|id_ed25519)(\.pub)?$'),
107
+ re.compile(r'(\.netrc|\.pgpass|\.htpasswd)$', re.IGNORECASE),
108
+ re.compile(r'(aws_credentials|gcloud_credentials|service.account)', re.IGNORECASE),
109
+ ]
110
+
111
+ # Generic keyword patterns - these only count when the keyword is LOAD-BEARING
112
+ # in the filename (see _generic_keyword_hit), because a keyword buried mid-phrase
113
+ # in a long descriptive slug names a topic, not a credential store:
114
+ # "token-economics-of-recall.md" is a note ABOUT tokens; "api_token.txt" IS one.
115
+ # Uses lookarounds instead of \b so underscore-prefixed names like api_token.txt
116
+ # match. Both patterns use (?![a-zA-Z]) so that the trailing-underscore behavior
117
+ # is consistent: "secret_store.txt" IS flagged, "tokenizer.py" is NOT (because
118
+ # "i" after "token" is alpha and blocks the match).
119
+ # `token` is kept separate because its longer suffix "izer"/"ize" is the only
120
+ # common false-positive; other keywords have no such well-known derivatives.
121
+ _GENERIC_KEYWORD_PATTERNS = [
122
+ re.compile(r'(?<![a-zA-Z0-9])(credential|secret|passwd|password|private_key)s?(?![a-zA-Z])', re.IGNORECASE),
123
+ re.compile(r'(?<![a-zA-Z0-9])tokens?(?![a-zA-Z])', re.IGNORECASE),
124
+ ]
125
+
126
+ # Word separators for the load-bearing check (underscore intentionally included;
127
+ # multi-word keywords like private_key are handled by the end-of-stem check,
128
+ # which runs before word counting).
129
+ _WORD_SPLIT = re.compile(r'[-_\s]+')
130
+
131
+
132
+ def _generic_keyword_hit(name: str) -> bool:
133
+ """True if a generic secret keyword appears load-bearing in the filename.
134
+
135
+ Secret-store files name their contents, and in English compounds the
136
+ content noun is the head, which comes last: "github-personal-access-token",
137
+ "api_token", "oauth_token". A keyword that is neither at the end of the
138
+ stem nor in a short (<=2 word) name is a topic word in a descriptive slug
139
+ ("token-economics-of-recall.md", "password-policy-discussion.md") and must
140
+ not cause the file to be silently dropped from the graph (#436, #718).
141
+ """
142
+ # Stem = name up to the first dot, ignoring leading dots so dotfiles like
143
+ # ".token" keep their keyword ("" stems would never match).
144
+ stem = name.lstrip('.').split('.')[0]
145
+ for pat in _GENERIC_KEYWORD_PATTERNS:
146
+ hit = False
147
+ for m in pat.finditer(stem):
148
+ hit = True
149
+ if m.end() == len(stem): # keyword ends the stem -> names the contents
150
+ return True
151
+ if hit and len([w for w in _WORD_SPLIT.split(stem) if w]) <= 2:
152
+ return True # short name like token_config.yaml / secret_handler.txt
153
+ return False
154
+
155
+ # Signals that a .md/.txt file is actually a converted academic paper
156
+ _PAPER_SIGNALS = [
157
+ re.compile(r'\barxiv\b', re.IGNORECASE),
158
+ re.compile(r'\bdoi\s*:', re.IGNORECASE),
159
+ re.compile(r'\babstract\b', re.IGNORECASE),
160
+ re.compile(r'\bproceedings\b', re.IGNORECASE),
161
+ re.compile(r'\bjournal\b', re.IGNORECASE),
162
+ re.compile(r'\bpreprint\b', re.IGNORECASE),
163
+ re.compile(r'\\cite\{'), # LaTeX citation
164
+ re.compile(r'\[\d+\]'), # Numbered citation [1], [23] (inline)
165
+ re.compile(r'\[\n\d+\n\]'), # Numbered citation spread across lines (markdown conversion)
166
+ re.compile(r'eq\.\s*\d+|equation\s+\d+', re.IGNORECASE),
167
+ re.compile(r'\d{4}\.\d{4,5}'), # arXiv ID like 1706.03762
168
+ re.compile(r'\bwe propose\b', re.IGNORECASE), # common academic phrasing
169
+ re.compile(r'\bliterature\b', re.IGNORECASE), # "from the literature"
170
+ ]
171
+ _PAPER_SIGNAL_THRESHOLD = 3 # need at least this many signals to call it a paper
172
+
173
+
174
+ def _is_sensitive(path: Path) -> bool:
175
+ """Return True if this file likely contains secrets and should be skipped."""
176
+ # Stage 1: any PARENT directory is a known secrets dir (parts[:-1] excludes
177
+ # the filename itself so a root-level file named "credentials" is not falsely
178
+ # skipped — the name patterns in Stage 2 handle the filename).
179
+ if any(part in _SENSITIVE_DIRS for part in path.parts[:-1]):
180
+ return True
181
+ # Stage 2: filename pattern match
182
+ name = path.name
183
+ if any(p.search(name) for p in _SENSITIVE_PATTERNS):
184
+ return True
185
+ # Stage 3: generic keywords, only when load-bearing in the name
186
+ return _generic_keyword_hit(name)
187
+
188
+
189
+ def _looks_like_paper(path: Path) -> bool:
190
+ """Heuristic: does this text file read like an academic paper?"""
191
+ try:
192
+ # Only scan first 3000 chars for speed
193
+ text = path.read_text(encoding="utf-8", errors="ignore")[:3000]
194
+ hits = sum(1 for pattern in _PAPER_SIGNALS if pattern.search(text))
195
+ return hits >= _PAPER_SIGNAL_THRESHOLD
196
+ except Exception:
197
+ return False
198
+
199
+
200
+ _ASSET_DIR_MARKERS = {".imageset", ".xcassets", ".appiconset", ".colorset", ".launchimage"}
201
+
202
+
203
+ _SHEBANG_CODE_INTERPRETERS = {
204
+ "python", "python3", "python2",
205
+ "ruby", "perl", "node", "nodejs",
206
+ "bash", "sh", "dash", "zsh", "fish", "ksh", "tcsh",
207
+ "lua", "php", "julia", "Rscript",
208
+ }
209
+
210
+
211
+ def _split_env_s(value: str, rest: list[str]) -> list[str]:
212
+ """Re-tokenize an `env -S`/`--split-string` packed command, prepending the
213
+ operand to any trailing args. Returns the unpacked argv."""
214
+ packed = " ".join([value, *rest]).strip()
215
+ return shlex.split(packed)
216
+
217
+
218
+ def _env_command_args(args: list[str], *, allow_split: bool = True) -> list[str]:
219
+ """Strip leading env(1) options and var assignments, return the trailing
220
+ command argv. Covers macOS/BSD and GNU coreutils env documented spellings.
221
+
222
+ POSIX/macOS short forms:
223
+ env [-0iv] [-C workdir] [-P utilpath] [-S string]
224
+ [-u name] [name=value ...] [utility [argument ...]]
225
+
226
+ GNU coreutils long/compact forms additionally supported:
227
+ --argv0=ARG / -a ARG / -aARG
228
+ --unset=NAME / --unset NAME / -u NAME / -uNAME
229
+ --chdir=DIR / --chdir DIR / -C DIR / -CDIR
230
+ --split-string=STRING / --split-string STRING
231
+ -S STRING / -SSTRING / -vS STRING / -vSSTRING
232
+ --ignore-environment / --null / --debug / --list-signal-handling
233
+ --default-signal[=SIG] / --ignore-signal[=SIG] / --block-signal[=SIG]
234
+
235
+ `-S` / `--split-string` payloads are themselves env-style argument lists
236
+ per the GNU shebang synopsis:
237
+ #!/usr/bin/env -[v]S[option]... [name=value]... command [args]...
238
+ so after splitting the payload we recursively re-parse it with
239
+ `allow_split=False` (a nested -S inside a split payload is rejected to
240
+ bound recursion).
241
+
242
+ Unknown hyphen-prefixed args yield [] (we refuse to guess whether
243
+ their next token is an interpreter or an operand).
244
+ """
245
+ i = 0
246
+ while i < len(args):
247
+ arg = args[i]
248
+
249
+ if arg == "--":
250
+ return args[i + 1:]
251
+
252
+ # Split-string forms: tokenize the packed payload, then re-parse it
253
+ # as env args (so leading assignments/flags inside the payload are
254
+ # skipped before the interpreter is identified).
255
+ if allow_split:
256
+ if arg == "-S":
257
+ if i + 1 >= len(args):
258
+ return []
259
+ return _env_command_args(
260
+ _split_env_s(" ".join(args[i + 1:]), []),
261
+ allow_split=False,
262
+ )
263
+ if arg.startswith("-S") and len(arg) > 2:
264
+ return _env_command_args(
265
+ _split_env_s(arg[2:], args[i + 1:]),
266
+ allow_split=False,
267
+ )
268
+ if arg == "-vS":
269
+ if i + 1 >= len(args):
270
+ return []
271
+ return _env_command_args(
272
+ _split_env_s(" ".join(args[i + 1:]), []),
273
+ allow_split=False,
274
+ )
275
+ if arg.startswith("-vS") and len(arg) > 3:
276
+ return _env_command_args(
277
+ _split_env_s(arg[3:], args[i + 1:]),
278
+ allow_split=False,
279
+ )
280
+ if arg.startswith("--split-string="):
281
+ return _env_command_args(
282
+ _split_env_s(arg.split("=", 1)[1], args[i + 1:]),
283
+ allow_split=False,
284
+ )
285
+ if arg == "--split-string":
286
+ if i + 1 >= len(args):
287
+ return []
288
+ return _env_command_args(
289
+ _split_env_s(args[i + 1], args[i + 2:]),
290
+ allow_split=False,
291
+ )
292
+
293
+ # Options with separate required operand
294
+ if arg in {"-u", "-C", "-P", "-a", "--unset", "--chdir", "--argv0"}:
295
+ if i + 2 > len(args):
296
+ return []
297
+ i += 2
298
+ continue
299
+
300
+ # Clumped short option + operand
301
+ if (
302
+ arg.startswith(("-u", "-C", "-P", "-a"))
303
+ and len(arg) > 2
304
+ and not arg.startswith("--")
305
+ ):
306
+ i += 1
307
+ continue
308
+
309
+ # Long option with `=` operand
310
+ if arg.startswith(("--unset=", "--chdir=", "--argv0=")):
311
+ i += 1
312
+ continue
313
+
314
+ # No-operand flags
315
+ if arg in {"-", "-i", "-0", "-v", "--ignore-environment", "--null",
316
+ "--debug", "--list-signal-handling"}:
317
+ i += 1
318
+ continue
319
+
320
+ # Signal-handling long flags (with or without =SIG operand — we treat
321
+ # them as no-effect for interpreter-resolution purposes)
322
+ if arg.startswith(("--default-signal", "--ignore-signal", "--block-signal")):
323
+ i += 1
324
+ continue
325
+
326
+ # Unknown hyphen-prefixed: refuse to guess
327
+ if arg.startswith("-"):
328
+ return []
329
+
330
+ # Inline NAME=value assignment
331
+ if "=" in arg:
332
+ i += 1
333
+ continue
334
+
335
+ # First non-option, non-assignment token starts the command argv
336
+ return args[i:]
337
+
338
+ return []
339
+
340
+
341
+ def _shebang_interpreter(path: Path) -> str | None:
342
+ """Return the interpreter name from a shebang line.
343
+
344
+ Handles forms that a naive parser misses:
345
+ - `#!/usr/bin/env -S python3 -u` (env -S split-args form, anywhere)
346
+ - `#!/usr/bin/env -i bash` (no-operand env flags)
347
+ - `#!/usr/bin/env -u VAR python3` (env options with operands)
348
+ - `#!/usr/bin/env -C /tmp python3` (env -C workdir)
349
+ - `#!/usr/bin/env -P /bin python3` (env -P utilpath)
350
+ - `#!/usr/bin/env DEBUG=1 python3` (inline var assignment)
351
+ - `#!"/usr/local/bin/python with spaces"` (shlex handles quotes)
352
+
353
+ Returns the basename of the resolved interpreter, or None if there is
354
+ no shebang / the file is unreadable / parsing fails.
355
+ """
356
+ try:
357
+ with path.open("rb") as f:
358
+ first = f.read(256)
359
+ if not first.startswith(b"#!"):
360
+ return None
361
+ line = first.split(b"\n")[0].decode(errors="replace")[2:].strip()
362
+ parts = shlex.split(line)
363
+ if not parts:
364
+ return None
365
+ interp = Path(parts[0]).name
366
+ if interp == "env":
367
+ env_args = _env_command_args(parts[1:])
368
+ if not env_args:
369
+ return None
370
+ interp = Path(env_args[0]).name
371
+ return interp
372
+ except (OSError, ValueError):
373
+ return None
374
+
375
+
376
+ def _shebang_file_type(path: Path) -> FileType | None:
377
+ """Peek at the first line of an extensionless file for a shebang."""
378
+ interp = _shebang_interpreter(path)
379
+ if interp in _SHEBANG_CODE_INTERPRETERS:
380
+ return FileType.CODE
381
+ return None
382
+
383
+
384
+ def classify_file(path: Path) -> FileType | None:
385
+ # Compound extensions must be checked before simple suffix lookup
386
+ if path.name.lower().endswith(".blade.php"):
387
+ return FileType.CODE
388
+ ext = path.suffix.lower()
389
+ if not ext:
390
+ return _shebang_file_type(path)
391
+ if ext in CODE_EXTENSIONS:
392
+ return FileType.CODE
393
+ if ext in PAPER_EXTENSIONS:
394
+ # PDFs inside Xcode asset catalogs are vector icons, not papers
395
+ if any(part.endswith(tuple(_ASSET_DIR_MARKERS)) for part in path.parts):
396
+ return None
397
+ return FileType.PAPER
398
+ if ext in IMAGE_EXTENSIONS:
399
+ return FileType.IMAGE
400
+ if ext in DOC_EXTENSIONS:
401
+ # Check if it's a converted paper
402
+ if _looks_like_paper(path):
403
+ return FileType.PAPER
404
+ return FileType.DOCUMENT
405
+ if ext in OFFICE_EXTENSIONS:
406
+ return FileType.DOCUMENT
407
+ if ext in GOOGLE_WORKSPACE_EXTENSIONS:
408
+ return FileType.DOCUMENT
409
+ if ext in VIDEO_EXTENSIONS:
410
+ return FileType.VIDEO
411
+ return None
412
+
413
+
414
+ def extract_pdf_text(path: Path) -> str:
415
+ """Extract plain text from a PDF file using pypdf."""
416
+ if not _file_within_size_cap(path):
417
+ return ""
418
+ try:
419
+ from pypdf import PdfReader
420
+ reader = PdfReader(str(path))
421
+ pages = []
422
+ for page in reader.pages:
423
+ text = page.extract_text()
424
+ if text:
425
+ pages.append(text)
426
+ return "\n".join(pages)
427
+ except Exception:
428
+ return ""
429
+
430
+
431
+ def docx_to_markdown(path: Path) -> str:
432
+ """Convert a .docx file to markdown text using python-docx."""
433
+ if not _zip_within_caps(path):
434
+ return ""
435
+ try:
436
+ from docx import Document
437
+ from docx.oxml.ns import qn
438
+ doc = Document(str(path))
439
+ lines = []
440
+ for para in doc.paragraphs:
441
+ style = para.style.name if para.style else ""
442
+ text = para.text.strip()
443
+ if not text:
444
+ lines.append("")
445
+ continue
446
+ if style.startswith("Heading 1"):
447
+ lines.append(f"# {text}")
448
+ elif style.startswith("Heading 2"):
449
+ lines.append(f"## {text}")
450
+ elif style.startswith("Heading 3"):
451
+ lines.append(f"### {text}")
452
+ elif style.startswith("List"):
453
+ lines.append(f"- {text}")
454
+ else:
455
+ lines.append(text)
456
+ # Tables
457
+ for table in doc.tables:
458
+ rows = [[cell.text.strip() for cell in row.cells] for row in table.rows]
459
+ if not rows:
460
+ continue
461
+ header = "| " + " | ".join(rows[0]) + " |"
462
+ sep = "| " + " | ".join("---" for _ in rows[0]) + " |"
463
+ lines.extend([header, sep])
464
+ for row in rows[1:]:
465
+ lines.append("| " + " | ".join(row) + " |")
466
+ return "\n".join(lines)
467
+ except ImportError:
468
+ return ""
469
+ except Exception:
470
+ return ""
471
+
472
+
473
+ def xlsx_to_markdown(path: Path) -> str:
474
+ """Convert an .xlsx file to markdown text using openpyxl."""
475
+ if not _zip_within_caps(path):
476
+ return ""
477
+ try:
478
+ import openpyxl
479
+ wb = openpyxl.load_workbook(str(path), read_only=True, data_only=True)
480
+ sections = []
481
+ for sheet_name in wb.sheetnames:
482
+ ws = wb[sheet_name]
483
+ rows = []
484
+ for row in ws.iter_rows(values_only=True):
485
+ if all(cell is None for cell in row):
486
+ continue
487
+ rows.append([str(cell) if cell is not None else "" for cell in row])
488
+ if not rows:
489
+ continue
490
+ sections.append(f"## Sheet: {sheet_name}")
491
+ if len(rows) >= 1:
492
+ header = "| " + " | ".join(rows[0]) + " |"
493
+ sep = "| " + " | ".join("---" for _ in rows[0]) + " |"
494
+ sections.extend([header, sep])
495
+ for row in rows[1:]:
496
+ sections.append("| " + " | ".join(row) + " |")
497
+ wb.close()
498
+ return "\n".join(sections)
499
+ except ImportError:
500
+ return ""
501
+ except Exception:
502
+ return ""
503
+
504
+
505
+ def xlsx_extract_structure(path: Path) -> dict:
506
+ """Extract structural nodes (sheets, named tables, column headers) from an .xlsx file.
507
+
508
+ Returns a nodes/edges dict compatible with the graphify extract pipeline.
509
+ Used in addition to xlsx_to_markdown so Claude sees both structure and content.
510
+ """
511
+ def _nid(*parts: str) -> str:
512
+ return re.sub(r"[^a-z0-9_]", "_", "_".join(p.lower() for p in parts).strip("_"))
513
+
514
+ try:
515
+ import openpyxl
516
+ except ImportError:
517
+ return {"nodes": [], "edges": []}
518
+
519
+ try:
520
+ wb = openpyxl.load_workbook(str(path), read_only=False, data_only=True)
521
+ except Exception:
522
+ return {"nodes": [], "edges": []}
523
+
524
+ # F-035: typo fix — was `_re.sub` (NameError, but unreachable because the
525
+ # whole xlsx codepath is currently behind a feature flag / not yet wired
526
+ # into the dispatcher). Before re-enabling this path, re-audit it for
527
+ # zip/XML bombs (openpyxl is built on top of zipfile and lxml-style XML
528
+ # parsing — a malicious .xlsx can blow up memory at load_workbook time).
529
+ stem = re.sub(r"[^a-z0-9]", "_", path.stem.lower())
530
+ str_path = str(path)
531
+ file_nid = _nid(str_path)
532
+ nodes: list[dict] = [{"id": file_nid, "label": path.name, "file_type": "document",
533
+ "source_file": str_path, "source_location": None}]
534
+ edges: list[dict] = []
535
+ seen: set[str] = {file_nid}
536
+
537
+ def _add(nid: str, label: str) -> None:
538
+ if nid not in seen:
539
+ seen.add(nid)
540
+ nodes.append({"id": nid, "label": label, "file_type": "document",
541
+ "source_file": str_path, "source_location": None})
542
+
543
+ def _edge(src: str, tgt: str, relation: str) -> None:
544
+ edges.append({"source": src, "target": tgt, "relation": relation,
545
+ "confidence": "EXTRACTED", "source_file": str_path,
546
+ "source_location": None, "weight": 1.0})
547
+
548
+ for sheet_name in wb.sheetnames:
549
+ ws = wb[sheet_name]
550
+ sheet_nid = _nid(stem, sheet_name)
551
+ _add(sheet_nid, f"{sheet_name} (sheet)")
552
+ _edge(file_nid, sheet_nid, "contains")
553
+
554
+ # Named Excel Tables (ListObjects)
555
+ if hasattr(ws, "tables"):
556
+ for tbl in ws.tables.values():
557
+ tbl_nid = _nid(stem, sheet_name, tbl.name)
558
+ _add(tbl_nid, tbl.name)
559
+ _edge(sheet_nid, tbl_nid, "contains")
560
+ # Column headers from table header row
561
+ ref = tbl.ref # e.g. "A1:D10"
562
+ if ref:
563
+ try:
564
+ from openpyxl.utils import range_boundaries
565
+ min_col, min_row, max_col, _ = range_boundaries(ref)
566
+ header_row = list(ws.iter_rows(min_row=min_row, max_row=min_row,
567
+ min_col=min_col, max_col=max_col,
568
+ values_only=True))
569
+ if header_row:
570
+ for col_name in header_row[0]:
571
+ if col_name:
572
+ col_nid = _nid(stem, tbl.name, str(col_name))
573
+ _add(col_nid, str(col_name))
574
+ _edge(tbl_nid, col_nid, "contains")
575
+ except Exception:
576
+ pass
577
+ else:
578
+ # Fallback: first non-empty row as column headers
579
+ for row in ws.iter_rows(max_row=1, values_only=True):
580
+ for cell in row:
581
+ if cell:
582
+ col_nid = _nid(stem, sheet_name, str(cell))
583
+ _add(col_nid, str(cell))
584
+ _edge(sheet_nid, col_nid, "contains")
585
+ break
586
+
587
+ try:
588
+ wb.close()
589
+ except Exception:
590
+ pass
591
+
592
+ return {"nodes": nodes, "edges": edges}
593
+
594
+
595
+ def convert_office_file(path: Path, out_dir: Path) -> Path | None:
596
+ """Convert a .docx or .xlsx to a markdown sidecar in out_dir.
597
+
598
+ Returns the path of the converted .md file, or None if conversion failed
599
+ or the required library is not installed.
600
+ """
601
+ ext = path.suffix.lower()
602
+ if ext == ".docx":
603
+ text = docx_to_markdown(path)
604
+ elif ext == ".xlsx":
605
+ text = xlsx_to_markdown(path)
606
+ else:
607
+ return None
608
+
609
+ if not text.strip():
610
+ return None
611
+
612
+ out_dir.mkdir(parents=True, exist_ok=True)
613
+ # Use a stable name derived from the original path to avoid collisions
614
+ import hashlib
615
+ name_hash = hashlib.sha256(str(path.resolve()).encode()).hexdigest()[:8]
616
+ out_path = out_dir / f"{path.stem}_{name_hash}.md"
617
+ out_path.write_text(
618
+ f"<!-- converted from {path.name} -->\n\n{text}",
619
+ encoding="utf-8",
620
+ )
621
+ return out_path
622
+
623
+
624
+ def count_words(path: Path) -> int:
625
+ try:
626
+ ext = path.suffix.lower()
627
+ if ext == ".pdf":
628
+ return len(extract_pdf_text(path).split())
629
+ if ext == ".docx":
630
+ return len(docx_to_markdown(path).split())
631
+ if ext == ".xlsx":
632
+ return len(xlsx_to_markdown(path).split())
633
+ return len(path.read_text(encoding="utf-8", errors="ignore").split())
634
+ except Exception:
635
+ return 0
636
+
637
+
638
+ # Directory names to always skip - venvs, caches, build artifacts, deps
639
+ _SKIP_DIRS = {
640
+ "venv", ".venv", "env", ".env",
641
+ "node_modules", "__pycache__", ".git",
642
+ "dist", "build", "target", "out",
643
+ "site-packages", "lib64",
644
+ ".pytest_cache", ".mypy_cache", ".ruff_cache",
645
+ ".tox", ".eggs", "*.egg-info",
646
+ "graphify-out", # never treat own output as source input (#524)
647
+ # Coverage/test-artefact dirs — generated, never architecturally meaningful
648
+ "coverage", "lcov-report", # Vitest/Istanbul/nyc HTML reports (#870)
649
+ "visual-tests", "visual-test", # Playwright/visual-regression bundles (#869)
650
+ "__snapshots__", "snapshots", # Jest/Vitest snapshot dirs
651
+ "storybook-static", # Storybook production build output
652
+ "dist-protected", # Protected dist variants (same noise as dist)
653
+ # Framework cache/build dirs — generated, never architecturally meaningful (#873)
654
+ ".next", ".nuxt", ".turbo", ".angular",
655
+ ".idea", ".cache", ".parcel-cache", ".svelte-kit", ".terraform", ".serverless",
656
+ ".graphify", # graphify's own extraction cache — never index self-generated data
657
+ ".worktrees", # git worktree convention (#947) — sibling checkouts, always redundant
658
+ }
659
+
660
+ # Large generated files that are never useful to extract
661
+ _SKIP_FILES = {
662
+ "package-lock.json", "yarn.lock", "pnpm-lock.yaml",
663
+ "Cargo.lock", "poetry.lock", "Gemfile.lock",
664
+ "composer.lock", "go.sum", "go.work.sum",
665
+ }
666
+
667
+ def _is_noise_dir(part: str, parent: "Path | None" = None) -> bool:
668
+ """Return True if this directory name looks like a venv, cache, or dep dir."""
669
+ if part in _SKIP_DIRS:
670
+ return True
671
+ # Catch *_venv, *_repo/site-packages patterns
672
+ if part.endswith("_venv") or part.endswith("_env"):
673
+ return True
674
+ if part.endswith(".egg-info"):
675
+ return True
676
+ # worktrees/ nested inside a dotted dir (e.g. .claude/worktrees/, .git/worktrees/)
677
+ if part == "worktrees" and parent is not None and parent.name.startswith("."):
678
+ return True
679
+ return False
680
+
681
+
682
+ _VCS_MARKERS = (".git", ".hg", ".svn", "_darcs", ".fossil")
683
+
684
+
685
+ def _parse_gitignore_line(raw: str) -> str:
686
+ """Parse one raw line from a .graphifyignore file per gitignore spec.
687
+
688
+ - Strip newline chars
689
+ - Strip inline comments (whitespace + # suffix), but only when # is
690
+ preceded by whitespace — so path#with#hash.py is preserved
691
+ - Unescape \\# to literal #
692
+ - Remove trailing spaces unless escaped with backslash
693
+ - Strip leading whitespace
694
+ - Return empty string for blank lines and full-line comments
695
+ """
696
+ line = raw.rstrip("\n\r")
697
+ line = line.lstrip()
698
+ if not line or line.startswith("#"):
699
+ return ""
700
+ # Strip inline comments: require whitespace before # (gitignore extension)
701
+ line = re.sub(r"\s+#+[^\\].*$", "", line)
702
+ # Unescape \# → literal #
703
+ line = line.replace("\\#", "#")
704
+ # Remove unescaped trailing spaces (per gitignore spec)
705
+ line = re.sub(r"(?<!\\) +$", "", line)
706
+ return line
707
+
708
+
709
+ def _find_vcs_root(start: Path) -> Path | None:
710
+ """Walk upward from start; return the first directory containing a VCS marker."""
711
+ current = start.resolve()
712
+ home = Path.home()
713
+ while True:
714
+ if any((current / m).exists() for m in _VCS_MARKERS):
715
+ return current
716
+ parent = current.parent
717
+ if parent == current or current == home:
718
+ return None
719
+ current = parent
720
+
721
+
722
+ def _load_graphifyignore(root: Path) -> list[tuple[Path, str]]:
723
+ """Read .graphifyignore files and return (anchor_dir, pattern) pairs.
724
+
725
+ Patterns are returned outer-first so that inner (closer) rules are
726
+ appended last and win via last-match-wins semantics — matching gitignore
727
+ behavior exactly.
728
+
729
+ Walk ceiling: the nearest VCS root if inside a repo, otherwise the scan
730
+ root itself (hermetic — no leakage across unrelated sibling projects).
731
+ """
732
+ root = root.resolve()
733
+ ceiling = _find_vcs_root(root) or root
734
+
735
+ # Collect ancestor dirs from ceiling down to root (outer → inner)
736
+ dirs: list[Path] = []
737
+ current = root
738
+ while True:
739
+ dirs.append(current)
740
+ if current == ceiling:
741
+ break
742
+ current = current.parent
743
+ dirs.reverse() # ceiling first, scan root last
744
+
745
+ patterns: list[tuple[Path, str]] = []
746
+ for d in dirs:
747
+ # Prefer .graphifyignore; fall back to .gitignore so projects that already
748
+ # maintain a .gitignore get sensible defaults without duplicating it (#945).
749
+ ignore_file = d / ".graphifyignore"
750
+ if not ignore_file.exists():
751
+ ignore_file = d / ".gitignore"
752
+ if ignore_file.exists():
753
+ for raw in ignore_file.read_text(encoding="utf-8", errors="ignore").splitlines():
754
+ line = _parse_gitignore_line(raw)
755
+ if line:
756
+ patterns.append((d, line))
757
+ return patterns
758
+
759
+
760
+ def _is_ignored(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
761
+ """Return True if the path should be ignored per .graphifyignore patterns.
762
+
763
+ Uses gitignore last-match-wins semantics: all patterns are evaluated in
764
+ order; the final matching pattern determines the result. Negation patterns
765
+ (starting with !) un-ignore a previously ignored path.
766
+
767
+ Enforces gitignore's parent-exclusion rule: a ! pattern cannot re-include
768
+ a file whose ancestor directory is already excluded.
769
+ """
770
+ if not patterns:
771
+ return False
772
+
773
+ def _eval(target: Path) -> bool:
774
+ """Apply last-match-wins to a single target path."""
775
+ def _matches(rel: str, p: str, anchored: bool) -> bool:
776
+ if anchored:
777
+ return fnmatch.fnmatch(rel, p)
778
+ parts = rel.split("/")
779
+ if fnmatch.fnmatch(rel, p):
780
+ return True
781
+ if fnmatch.fnmatch(target.name, p):
782
+ return True
783
+ for i, part in enumerate(parts):
784
+ if fnmatch.fnmatch(part, p):
785
+ return True
786
+ if fnmatch.fnmatch("/".join(parts[:i + 1]), p):
787
+ return True
788
+ return False
789
+
790
+ result = False
791
+ for anchor, pattern in patterns:
792
+ negated = pattern.startswith("!")
793
+ raw = pattern[1:] if negated else pattern
794
+ anchored = raw.startswith("/")
795
+ p = raw.strip("/")
796
+ if not p:
797
+ continue
798
+
799
+ matched = False
800
+ if anchored:
801
+ try:
802
+ rel_anchor = str(target.relative_to(anchor)).replace(os.sep, "/")
803
+ matched = _matches(rel_anchor, p, anchored=True)
804
+ except ValueError:
805
+ pass
806
+ else:
807
+ try:
808
+ rel = str(target.relative_to(root)).replace(os.sep, "/")
809
+ matched = _matches(rel, p, anchored=False)
810
+ except ValueError:
811
+ pass
812
+ if not matched and anchor != root:
813
+ try:
814
+ rel_anchor = str(target.relative_to(anchor)).replace(os.sep, "/")
815
+ matched = _matches(rel_anchor, p, anchored=False)
816
+ except ValueError:
817
+ pass
818
+
819
+ if matched:
820
+ result = not negated # last match wins; ! flips to un-ignore
821
+ return result
822
+
823
+ # Gitignore parent-exclusion rule: a ! re-include cannot rescue a file
824
+ # whose ancestor directory is already excluded. Walk ancestors top-down;
825
+ # if any ancestor is excluded, the file is excluded regardless of later
826
+ # ! patterns targeting the file or a sub-path.
827
+ try:
828
+ rel_parts = path.relative_to(root).parts
829
+ except ValueError:
830
+ return _eval(path)
831
+
832
+ ancestor = root
833
+ for part in rel_parts[:-1]:
834
+ ancestor = ancestor / part
835
+ if _eval(ancestor):
836
+ return True
837
+ return _eval(path)
838
+
839
+
840
+ def _load_graphifyinclude(root: Path) -> list[tuple[Path, str]]:
841
+ """Read .graphifyinclude allowlist patterns from root and ancestors.
842
+
843
+ Include patterns opt matching hidden files/dirs into traversal. Sensitive
844
+ files and hard-skipped noise directories are still excluded later.
845
+ Uses the same VCS-root ceiling logic as _load_graphifyignore.
846
+ """
847
+ root = root.resolve()
848
+ ceiling = _find_vcs_root(root) or root
849
+
850
+ dirs: list[Path] = []
851
+ current = root
852
+ while True:
853
+ dirs.append(current)
854
+ if current == ceiling:
855
+ break
856
+ current = current.parent
857
+ dirs.reverse()
858
+
859
+ patterns: list[tuple[Path, str]] = []
860
+ for d in dirs:
861
+ include_file = d / ".graphifyinclude"
862
+ if include_file.exists():
863
+ for raw in include_file.read_text(encoding="utf-8", errors="ignore").splitlines():
864
+ line = _parse_gitignore_line(raw)
865
+ if line:
866
+ patterns.append((d, line))
867
+ return patterns
868
+
869
+
870
+ def _is_included(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
871
+ """Return True if path matches any .graphifyinclude allowlist pattern."""
872
+ if not patterns:
873
+ return False
874
+
875
+ def _matches(rel: str, p: str, anchored: bool) -> bool:
876
+ if anchored:
877
+ return fnmatch.fnmatch(rel, p)
878
+ parts = rel.split("/")
879
+ if fnmatch.fnmatch(rel, p):
880
+ return True
881
+ if fnmatch.fnmatch(path.name, p):
882
+ return True
883
+ for i, part in enumerate(parts):
884
+ if fnmatch.fnmatch(part, p):
885
+ return True
886
+ if fnmatch.fnmatch("/".join(parts[:i + 1]), p):
887
+ return True
888
+ return False
889
+
890
+ for anchor, pattern in patterns:
891
+ anchored = pattern.startswith("/")
892
+ p = pattern.strip("/")
893
+ if not p:
894
+ continue
895
+ if anchored:
896
+ try:
897
+ rel_anchor = str(path.relative_to(anchor)).replace(os.sep, "/")
898
+ if _matches(rel_anchor, p, anchored=True):
899
+ return True
900
+ except ValueError:
901
+ pass
902
+ else:
903
+ try:
904
+ rel = str(path.relative_to(root)).replace(os.sep, "/")
905
+ if _matches(rel, p, anchored=False):
906
+ return True
907
+ except ValueError:
908
+ pass
909
+ if anchor != root:
910
+ try:
911
+ rel_anchor = str(path.relative_to(anchor)).replace(os.sep, "/")
912
+ if _matches(rel_anchor, p, anchored=False):
913
+ return True
914
+ except ValueError:
915
+ pass
916
+ return False
917
+
918
+
919
+ def _could_contain_included_path(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
920
+ """Return True if a directory may contain files matched by .graphifyinclude."""
921
+ if not patterns:
922
+ return False
923
+
924
+ rels: list[str] = []
925
+ try:
926
+ rels.append(str(path.relative_to(root)).replace(os.sep, "/"))
927
+ except ValueError:
928
+ pass
929
+ for anchor, _ in patterns:
930
+ if anchor != root:
931
+ try:
932
+ rels.append(str(path.relative_to(anchor)).replace(os.sep, "/"))
933
+ except ValueError:
934
+ pass
935
+
936
+ for rel in rels:
937
+ rel = rel.strip("/")
938
+ if not rel:
939
+ return True
940
+ for _, pattern in patterns:
941
+ p = pattern.strip("/")
942
+ if not p:
943
+ continue
944
+ if p == rel or p.startswith(rel + "/"):
945
+ return True
946
+ if fnmatch.fnmatch(rel, p):
947
+ return True
948
+ return False
949
+
950
+
951
+ def _auto_follow_symlinks(root: Path) -> bool:
952
+ """Auto-detect: ``True`` if ``root`` has any direct symlinked child.
953
+
954
+ Allows "fake working dir" patterns (e.g. a folder full of symlinks pointing
955
+ at scattered source dirs across the user's machine) to work transparently
956
+ without the caller having to know to pass ``follow_symlinks=True``.
957
+
958
+ Override is always possible by passing an explicit ``follow_symlinks=True``
959
+ or ``follow_symlinks=False`` to :func:`detect` / :func:`detect_incremental`.
960
+ """
961
+ try:
962
+ for p in root.iterdir():
963
+ if p.is_symlink():
964
+ return True
965
+ except (OSError, PermissionError):
966
+ pass
967
+ return False
968
+
969
+
970
+ def detect(root: Path, *, follow_symlinks: bool | None = None, google_workspace: bool | None = None, extra_excludes: list[str] | None = None) -> dict:
971
+ root = root.resolve()
972
+ if follow_symlinks is None:
973
+ follow_symlinks = _auto_follow_symlinks(root)
974
+ google_workspace = google_workspace_enabled() if google_workspace is None else google_workspace
975
+ files: dict[FileType, list[str]] = {
976
+ FileType.CODE: [],
977
+ FileType.DOCUMENT: [],
978
+ FileType.PAPER: [],
979
+ FileType.IMAGE: [],
980
+ FileType.VIDEO: [],
981
+ }
982
+ total_words = 0
983
+
984
+ skipped_sensitive: list[str] = []
985
+ ignore_patterns = _load_graphifyignore(root)
986
+ # CLI --exclude patterns are anchored at the scan root and appended last
987
+ # so they win over any .graphifyignore/.gitignore rules (#947).
988
+ if extra_excludes:
989
+ for pat in extra_excludes:
990
+ line = _parse_gitignore_line(pat)
991
+ if line:
992
+ ignore_patterns.append((root, line))
993
+ include_patterns = _load_graphifyinclude(root)
994
+
995
+ # Always include graphify-out/memory/ - query results filed back into the graph
996
+ memory_dir = root / "graphify-out" / "memory"
997
+ scan_paths = [root]
998
+ if memory_dir.exists():
999
+ scan_paths.append(memory_dir)
1000
+
1001
+ seen: set[Path] = set()
1002
+ all_files: list[Path] = []
1003
+
1004
+ for scan_root in scan_paths:
1005
+ in_memory_tree = memory_dir.exists() and str(scan_root).startswith(str(memory_dir))
1006
+ for dirpath, dirnames, filenames in os.walk(scan_root, followlinks=follow_symlinks):
1007
+ dp = Path(dirpath)
1008
+ if follow_symlinks and os.path.islink(dirpath):
1009
+ real = os.path.realpath(dirpath)
1010
+ parent_real = os.path.realpath(os.path.dirname(dirpath))
1011
+ if parent_real == real or parent_real.startswith(real + os.sep):
1012
+ dirnames.clear()
1013
+ continue
1014
+ if not in_memory_tree:
1015
+ # Prune noise dirs in-place so os.walk never descends into them.
1016
+ # Dot dirs are allowed — users often want .github/, .claude/, etc.
1017
+ # Framework caches (.next, .nuxt, …) are caught by _is_noise_dir.
1018
+ # When negation patterns (!) exist, skip directory-level ignore
1019
+ # pruning so negated files inside can still be reached.
1020
+ has_negation = any(p.startswith("!") for _, p in ignore_patterns)
1021
+ dirnames[:] = [
1022
+ d for d in dirnames
1023
+ if not _is_noise_dir(d, dp)
1024
+ and (has_negation or not _is_ignored(dp / d, root, ignore_patterns))
1025
+ ]
1026
+ for fname in filenames:
1027
+ if fname in _SKIP_FILES:
1028
+ continue
1029
+ p = dp / fname
1030
+ if p not in seen:
1031
+ seen.add(p)
1032
+ all_files.append(p)
1033
+
1034
+ all_files.sort(key=lambda p: str(p))
1035
+
1036
+ converted_dir = root / "graphify-out" / "converted"
1037
+
1038
+ for p in all_files:
1039
+ # For memory dir files, skip hidden/noise filtering
1040
+ in_memory = memory_dir.exists() and str(p).startswith(str(memory_dir))
1041
+ if not in_memory:
1042
+ # Skip files inside our own converted/ dir (avoid re-processing sidecars)
1043
+ if str(p).startswith(str(converted_dir)):
1044
+ continue
1045
+ if not in_memory and _is_ignored(p, root, ignore_patterns):
1046
+ continue
1047
+ if _is_sensitive(p):
1048
+ skipped_sensitive.append(str(p))
1049
+ continue
1050
+ ftype = classify_file(p)
1051
+ if ftype:
1052
+ if p.suffix.lower() in GOOGLE_WORKSPACE_EXTENSIONS:
1053
+ if not google_workspace:
1054
+ skipped_sensitive.append(
1055
+ str(p)
1056
+ + " [Google Workspace shortcut skipped - pass --google-workspace "
1057
+ "or set GRAPHIFY_GOOGLE_WORKSPACE=1]"
1058
+ )
1059
+ continue
1060
+ try:
1061
+ md_path = convert_google_workspace_file(p, converted_dir, xlsx_to_markdown=xlsx_to_markdown)
1062
+ except Exception as exc:
1063
+ skipped_sensitive.append(str(p) + f" [Google Workspace export failed: {exc}]")
1064
+ continue
1065
+ if md_path:
1066
+ if _is_ignored(md_path, root, ignore_patterns):
1067
+ continue
1068
+ files[ftype].append(str(md_path))
1069
+ total_words += count_words(md_path)
1070
+ else:
1071
+ skipped_sensitive.append(str(p) + " [Google Workspace export produced no readable text]")
1072
+ continue
1073
+ # Office files: convert to markdown sidecar so subagents can read them
1074
+ if p.suffix.lower() in OFFICE_EXTENSIONS:
1075
+ md_path = convert_office_file(p, converted_dir)
1076
+ if md_path:
1077
+ if _is_ignored(md_path, root, ignore_patterns):
1078
+ continue
1079
+ files[ftype].append(str(md_path))
1080
+ total_words += count_words(md_path)
1081
+ else:
1082
+ # Conversion failed (library not installed) - skip with note
1083
+ skipped_sensitive.append(str(p) + " [office conversion failed - pip install graphifyy[office]]")
1084
+ continue
1085
+ files[ftype].append(str(p))
1086
+ if ftype != FileType.VIDEO:
1087
+ total_words += count_words(p)
1088
+
1089
+ for ftype in files:
1090
+ files[ftype].sort()
1091
+
1092
+ total_files = sum(len(v) for v in files.values())
1093
+ needs_graph = total_words >= CORPUS_WARN_THRESHOLD
1094
+
1095
+ # Determine warning - lower bound, upper bound, or sensitive files skipped
1096
+ warning: str | None = None
1097
+ if not needs_graph:
1098
+ warning = (
1099
+ f"Corpus is ~{total_words:,} words - fits in a single context window. "
1100
+ f"You may not need a graph."
1101
+ )
1102
+ elif total_words >= CORPUS_UPPER_THRESHOLD or total_files >= FILE_COUNT_UPPER:
1103
+ warning = (
1104
+ f"Large corpus: {total_files} files · ~{total_words:,} words. "
1105
+ f"Semantic extraction will be expensive (many Claude tokens). "
1106
+ f"Consider running on a subfolder."
1107
+ )
1108
+
1109
+ return {
1110
+ "files": {k.value: v for k, v in files.items()},
1111
+ "total_files": total_files,
1112
+ "total_words": total_words,
1113
+ "needs_graph": needs_graph,
1114
+ "warning": warning,
1115
+ "skipped_sensitive": skipped_sensitive,
1116
+ "graphifyignore_patterns": len(ignore_patterns),
1117
+ "scan_root": str(root.resolve()),
1118
+ }
1119
+
1120
+
1121
+ def _md5_file(path: Path) -> str:
1122
+ """MD5 of file contents streamed in 64KB chunks — for change detection only."""
1123
+ import hashlib as _hl
1124
+ h = _hl.md5(usedforsecurity=False)
1125
+ try:
1126
+ with path.open("rb") as f:
1127
+ for chunk in iter(lambda: f.read(65536), b""):
1128
+ h.update(chunk)
1129
+ except OSError:
1130
+ return ""
1131
+ return h.hexdigest()
1132
+
1133
+
1134
+ def _to_relative_for_storage(key: str, root: Path) -> str:
1135
+ """Return ``key`` as a forward-slash relative path from ``root``.
1136
+
1137
+ Keys outside ``root`` (out-of-tree symlinked sources, external --include
1138
+ paths) and already-relative keys pass through unchanged — mirrors the
1139
+ fallback in :func:`graphify.watch._relativize_source_files` so the
1140
+ on-disk artifact survives the round-trip even when some paths cannot be
1141
+ portably encoded.
1142
+
1143
+ Only ``root`` is resolved — the key itself is relativized symbolically
1144
+ so an in-root symlink (e.g. ``alias.py -> sub/target.py``) is stored
1145
+ under its own name. Resolving the key would point the stored entry at
1146
+ the symlink target, and the original key would then miss on reload and
1147
+ re-extract on every incremental run.
1148
+ """
1149
+ p = Path(key)
1150
+ if not p.is_absolute():
1151
+ return key
1152
+ try:
1153
+ rel = os.path.relpath(p, Path(root).resolve())
1154
+ except (ValueError, OSError):
1155
+ return key # outside root (e.g. Windows cross-drive)
1156
+ # ``os.path.relpath`` happily produces ``../foo`` for paths outside
1157
+ # root; mirror the prior ``relative_to``-raises-ValueError semantics by
1158
+ # keeping out-of-root entries in their absolute form.
1159
+ if rel == ".." or rel.startswith(".." + os.sep) or rel.startswith("../"):
1160
+ return key
1161
+ return rel.replace(os.sep, "/")
1162
+
1163
+
1164
+ def _to_absolute_from_storage(key: str, root: Path) -> str:
1165
+ """Inverse of :func:`_to_relative_for_storage`.
1166
+
1167
+ Re-anchor a stored key against ``root``. Already-absolute keys
1168
+ (legacy manifests, out-of-root entries) pass through unchanged so
1169
+ that newly-loaded manifests from before this change remain readable.
1170
+ Uses ``Path(root).resolve()`` so the produced absolute path matches
1171
+ what :func:`detect` returns (which also resolves the scan root).
1172
+ """
1173
+ p = Path(key)
1174
+ if p.is_absolute():
1175
+ return str(p)
1176
+ return str(Path(root).resolve() / p)
1177
+
1178
+
1179
+ def load_manifest(
1180
+ manifest_path: str = _MANIFEST_PATH,
1181
+ *,
1182
+ root: Path | None = None,
1183
+ ) -> dict:
1184
+ """Load the manifest from a previous run. Returns {} on any error.
1185
+
1186
+ When ``root`` is provided, stored relative keys are re-anchored against
1187
+ it so callers see absolute paths regardless of on-disk format. Legacy
1188
+ manifests with absolute keys pass through unchanged, so a graphify-out/
1189
+ written by an older version (or by a caller that didn't supply ``root``
1190
+ to :func:`save_manifest`) remains readable.
1191
+ """
1192
+ try:
1193
+ raw = json.loads(Path(manifest_path).read_text(encoding="utf-8"))
1194
+ except Exception:
1195
+ return {}
1196
+ if root is None or not isinstance(raw, dict):
1197
+ return raw
1198
+ return {_to_absolute_from_storage(k, root): v for k, v in raw.items()}
1199
+
1200
+
1201
+ def save_manifest(
1202
+ files: dict[str, list[str]],
1203
+ manifest_path: str = _MANIFEST_PATH,
1204
+ *,
1205
+ kind: str = "both",
1206
+ root: Path | None = None,
1207
+ ) -> None:
1208
+ """Save current file mtimes + content hashes for change detection.
1209
+
1210
+ kind="ast" — written by `graphify update` (AST-only rebuild). Stamps
1211
+ ast_hash; preserves an existing semantic_hash only when
1212
+ the file content is unchanged (mtime + hash match).
1213
+ kind="semantic" — written by `graphify extract` after semantic extraction.
1214
+ Stamps semantic_hash; preserves existing ast_hash.
1215
+ kind="both" — full pipeline: stamps both hashes (default).
1216
+
1217
+ When ``root`` is provided, keys are relativized against it before write
1218
+ (forward-slash, posix-style) so the on-disk manifest is portable across
1219
+ machines and checkout locations (#777). Out-of-root entries are written
1220
+ as absolute so they continue to round-trip on the saving machine.
1221
+ When ``root`` is None the legacy absolute-keyed format is preserved.
1222
+ """
1223
+ existing = load_manifest(manifest_path, root=root)
1224
+
1225
+ def _normalise_entry(entry):
1226
+ if isinstance(entry, (int, float)):
1227
+ return {"mtime": entry, "ast_hash": "", "semantic_hash": ""}
1228
+ if isinstance(entry, dict) and "hash" in entry and "ast_hash" not in entry:
1229
+ return {"mtime": entry.get("mtime", 0), "ast_hash": entry["hash"], "semantic_hash": ""}
1230
+ if isinstance(entry, dict):
1231
+ return entry
1232
+ return None
1233
+
1234
+ # Seed from the existing manifest so incremental callers passing a subset
1235
+ # of files don't silently erase entries for untouched files (#917).
1236
+ # Prune entries whose file no longer exists on disk — those are genuine
1237
+ # deletions that detect_incremental() should treat as gone.
1238
+ manifest: dict[str, dict] = {}
1239
+ for f, entry in existing.items():
1240
+ normalised = _normalise_entry(entry)
1241
+ if normalised is None:
1242
+ continue
1243
+ try:
1244
+ if Path(f).exists():
1245
+ manifest[f] = normalised
1246
+ except OSError:
1247
+ continue
1248
+
1249
+ for file_list in files.values():
1250
+ for f in file_list:
1251
+ try:
1252
+ p = Path(f)
1253
+ mtime = p.stat().st_mtime
1254
+ h = _md5_file(p)
1255
+ except OSError:
1256
+ continue # file deleted between detect() and manifest write
1257
+ prev = _normalise_entry(existing.get(f, {})) or {}
1258
+ entry: dict = {"mtime": mtime}
1259
+ if kind in ("ast", "both"):
1260
+ entry["ast_hash"] = h
1261
+ else:
1262
+ entry["ast_hash"] = prev.get("ast_hash", "")
1263
+ if kind in ("semantic", "both"):
1264
+ entry["semantic_hash"] = h
1265
+ else:
1266
+ # Preserve semantic_hash only when content is unchanged
1267
+ entry["semantic_hash"] = prev.get("semantic_hash", "") if h == prev.get("ast_hash", "") else ""
1268
+ manifest[f] = entry
1269
+ if root is not None:
1270
+ # Persist in portable form: forward-slash relative paths. Keys outside
1271
+ # ``root`` (out-of-tree symlinked corpora, --include sources) keep
1272
+ # their absolute form so the manifest round-trips on the saving
1273
+ # machine even when not every entry can be portably encoded.
1274
+ manifest = {_to_relative_for_storage(k, root): v for k, v in manifest.items()}
1275
+ Path(manifest_path).parent.mkdir(parents=True, exist_ok=True)
1276
+ Path(manifest_path).write_text(json.dumps(manifest, indent=2), encoding="utf-8")
1277
+
1278
+
1279
+ def detect_incremental(
1280
+ root: Path,
1281
+ manifest_path: str = _MANIFEST_PATH,
1282
+ *,
1283
+ follow_symlinks: bool | None = None,
1284
+ google_workspace: bool | None = None,
1285
+ kind: str = "semantic",
1286
+ extra_excludes: list[str] | None = None,
1287
+ ) -> dict:
1288
+ """Like detect(), but returns only new or modified files since the last run.
1289
+
1290
+ kind="semantic" (default for extract): a file is "changed" when its
1291
+ semantic_hash is missing or its content has changed since the last
1292
+ semantic extraction pass. Use this for `graphify extract` so that
1293
+ files touched by `graphify update` (AST-only) are re-extracted
1294
+ semantically.
1295
+ kind="ast": a file is "changed" when its ast_hash is missing or its
1296
+ content has changed. Use this for `graphify update`.
1297
+
1298
+ Fast path: mtime unchanged + hash matches → unchanged (free, no disk IO
1299
+ beyond stat). Slow path: mtime bumped → compare MD5 against the relevant
1300
+ hash field before re-extracting.
1301
+
1302
+ Backwards compatible with legacy manifests storing plain float mtime values
1303
+ or {mtime, hash} dicts (treated as ast_hash only; semantic_hash = miss).
1304
+
1305
+ The ``follow_symlinks`` flag is forwarded to :func:`detect` so corpora that
1306
+ rely on symlinked sub-trees (e.g. a ``state_of_truth/`` symlink pointing to a
1307
+ directory outside the scan root) are scanned consistently between full and
1308
+ incremental runs. ``None`` (default) means auto-detect: ``True`` when ``root``
1309
+ contains at least one direct symlinked child, ``False`` otherwise.
1310
+ """
1311
+ full = detect(root, follow_symlinks=follow_symlinks, google_workspace=google_workspace, extra_excludes=extra_excludes)
1312
+ # Pass ``root`` so a manifest written with relative keys (post-#777) is
1313
+ # re-anchored to the absolute form the rest of this function compares
1314
+ # against. Legacy absolute-keyed manifests pass through unchanged.
1315
+ manifest = load_manifest(manifest_path, root=root)
1316
+
1317
+ if not manifest:
1318
+ # No previous run - treat everything as new
1319
+ full["incremental"] = True
1320
+ full["new_files"] = full["files"]
1321
+ full["unchanged_files"] = {k: [] for k in full["files"]}
1322
+ full["new_total"] = full["total_files"]
1323
+ return full
1324
+
1325
+ new_files: dict[str, list[str]] = {k: [] for k in full["files"]}
1326
+ unchanged_files: dict[str, list[str]] = {k: [] for k in full["files"]}
1327
+
1328
+ for ftype, file_list in full["files"].items():
1329
+ for f in file_list:
1330
+ stored = manifest.get(f)
1331
+ try:
1332
+ current_mtime = Path(f).stat().st_mtime
1333
+ except Exception:
1334
+ current_mtime = 0
1335
+
1336
+ # Legacy manifest: plain float value — treat as ast_hash only
1337
+ if isinstance(stored, (int, float)):
1338
+ changed = stored is None or current_mtime > stored
1339
+ elif isinstance(stored, dict):
1340
+ # Normalise legacy {mtime, hash} to new schema
1341
+ if "hash" in stored and "ast_hash" not in stored:
1342
+ stored = {"mtime": stored.get("mtime", 0), "ast_hash": stored["hash"], "semantic_hash": ""}
1343
+ hash_key = "semantic_hash" if kind == "semantic" else "ast_hash"
1344
+ stored_hash = stored.get(hash_key, "")
1345
+ # Missing semantic_hash means update ran but extract hasn't — always re-extract
1346
+ if not stored_hash:
1347
+ changed = True
1348
+ else:
1349
+ stored_mtime = stored.get("mtime")
1350
+ # Schema-drift guard (#1163): tolerate a nested {mtime: ...}
1351
+ # dict or any non-numeric value without crashing.
1352
+ if isinstance(stored_mtime, dict):
1353
+ stored_mtime = stored_mtime.get("mtime")
1354
+ if not isinstance(stored_mtime, (int, float)):
1355
+ stored_mtime = None
1356
+ if stored_mtime is None or current_mtime != stored_mtime:
1357
+ # mtime bumped — verify with content hash before re-extracting
1358
+ changed = _md5_file(Path(f)) != stored_hash
1359
+ else:
1360
+ changed = False
1361
+ else:
1362
+ changed = True # unknown format, re-extract to be safe
1363
+
1364
+ if changed:
1365
+ new_files[ftype].append(f)
1366
+ else:
1367
+ unchanged_files[ftype].append(f)
1368
+
1369
+ # Files in manifest that no longer exist - their cached nodes are now ghost nodes
1370
+ current_files = {f for flist in full["files"].values() for f in flist}
1371
+ deleted_files = [f for f in manifest if f not in current_files]
1372
+
1373
+ new_total = sum(len(v) for v in new_files.values())
1374
+ full["incremental"] = True
1375
+ full["new_files"] = new_files
1376
+ full["unchanged_files"] = unchanged_files
1377
+ full["new_total"] = new_total
1378
+ full["deleted_files"] = deleted_files
1379
+ return full