imhcode 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (986) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +39 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +29 -0
  4. package/.github/copilot-instructions.md +43 -0
  5. package/.github/workflows/framework-validator.yml +53 -0
  6. package/.gitignore.template +15 -0
  7. package/AGENTS.md +69 -0
  8. package/CLAUDE.md +27 -0
  9. package/README.md +63 -0
  10. package/SETUP.md +81 -0
  11. package/USER_MANUAL.md +70 -0
  12. package/agents/android-executor/SYSTEM.md +32 -0
  13. package/agents/android-executor/agent.yml +53 -0
  14. package/agents/debugger/SYSTEM.md +32 -0
  15. package/agents/debugger/agent.yml +56 -0
  16. package/agents/designer/SYSTEM.md +32 -0
  17. package/agents/designer/agent.yml +59 -0
  18. package/agents/devops-executor/SYSTEM.md +32 -0
  19. package/agents/devops-executor/agent.yml +56 -0
  20. package/agents/flutter-executor/SYSTEM.md +32 -0
  21. package/agents/flutter-executor/agent.yml +54 -0
  22. package/agents/ios-executor/SYSTEM.md +32 -0
  23. package/agents/ios-executor/agent.yml +53 -0
  24. package/agents/java-executor/SYSTEM.md +32 -0
  25. package/agents/java-executor/agent.yml +57 -0
  26. package/agents/laravel-executor/SYSTEM.md +32 -0
  27. package/agents/laravel-executor/agent.yml +59 -0
  28. package/agents/nextjs-executor/SYSTEM.md +32 -0
  29. package/agents/nextjs-executor/agent.yml +60 -0
  30. package/agents/planner/SYSTEM.md +32 -0
  31. package/agents/planner/agent.yml +56 -0
  32. package/agents/python-executor/SYSTEM.md +32 -0
  33. package/agents/python-executor/agent.yml +58 -0
  34. package/agents/react-executor/SYSTEM.md +32 -0
  35. package/agents/react-executor/agent.yml +58 -0
  36. package/agents/react-native-executor/SYSTEM.md +32 -0
  37. package/agents/react-native-executor/agent.yml +53 -0
  38. package/agents/security-auditor/SYSTEM.md +32 -0
  39. package/agents/security-auditor/agent.yml +56 -0
  40. package/agents/seo-optimizer/SYSTEM.md +32 -0
  41. package/agents/seo-optimizer/agent.yml +54 -0
  42. package/agents/systems-executor/SYSTEM.md +32 -0
  43. package/agents/systems-executor/agent.yml +54 -0
  44. package/agents/tester/SYSTEM.md +32 -0
  45. package/agents/tester/agent.yml +58 -0
  46. package/agents/vue-executor/SYSTEM.md +32 -0
  47. package/agents/vue-executor/agent.yml +58 -0
  48. package/agents/web3-executor/SYSTEM.md +32 -0
  49. package/agents/web3-executor/agent.yml +55 -0
  50. package/bin/imhcode.js +1634 -0
  51. package/dist/orchestrator/builder.d.ts +23 -0
  52. package/dist/orchestrator/builder.d.ts.map +1 -0
  53. package/dist/orchestrator/builder.js +231 -0
  54. package/dist/orchestrator/builder.js.map +1 -0
  55. package/dist/orchestrator/executor.d.ts +43 -0
  56. package/dist/orchestrator/executor.d.ts.map +1 -0
  57. package/dist/orchestrator/executor.js +356 -0
  58. package/dist/orchestrator/executor.js.map +1 -0
  59. package/dist/orchestrator/index.d.ts +35 -0
  60. package/dist/orchestrator/index.d.ts.map +1 -0
  61. package/dist/orchestrator/index.js +490 -0
  62. package/dist/orchestrator/index.js.map +1 -0
  63. package/dist/orchestrator/loader.d.ts +33 -0
  64. package/dist/orchestrator/loader.d.ts.map +1 -0
  65. package/dist/orchestrator/loader.js +203 -0
  66. package/dist/orchestrator/loader.js.map +1 -0
  67. package/dist/orchestrator/registry.d.ts +63 -0
  68. package/dist/orchestrator/registry.d.ts.map +1 -0
  69. package/dist/orchestrator/registry.js +181 -0
  70. package/dist/orchestrator/registry.js.map +1 -0
  71. package/dist/orchestrator/schema.d.ts +132 -0
  72. package/dist/orchestrator/schema.d.ts.map +1 -0
  73. package/dist/orchestrator/schema.js +101 -0
  74. package/dist/orchestrator/schema.js.map +1 -0
  75. package/dist/orchestrator/session.d.ts +25 -0
  76. package/dist/orchestrator/session.d.ts.map +1 -0
  77. package/dist/orchestrator/session.js +80 -0
  78. package/dist/orchestrator/session.js.map +1 -0
  79. package/dist/orchestrator/types.d.ts +91 -0
  80. package/dist/orchestrator/types.d.ts.map +1 -0
  81. package/dist/orchestrator/types.js +7 -0
  82. package/dist/orchestrator/types.js.map +1 -0
  83. package/package.json +95 -0
  84. package/skills/AnimatePresence/SKILL.md +3 -0
  85. package/skills/accessibility/SKILL.md +146 -0
  86. package/skills/agent-architecture-audit/SKILL.md +256 -0
  87. package/skills/agent-eval/SKILL.md +145 -0
  88. package/skills/agent-introspection-debugging/SKILL.md +153 -0
  89. package/skills/agentic-engineering/SKILL.md +63 -0
  90. package/skills/ai-regression-testing/SKILL.md +385 -0
  91. package/skills/android-clean-architecture/SKILL.md +339 -0
  92. package/skills/animated-component-libraries/SKILL.md +8 -0
  93. package/skills/animejs/SKILL.md +8 -0
  94. package/skills/api-connector-builder/SKILL.md +120 -0
  95. package/skills/api-design/SKILL.md +523 -0
  96. package/skills/apple/SKILL.md +158 -0
  97. package/skills/apple/metadata.json +16 -0
  98. package/skills/architecture-decision-records/SKILL.md +179 -0
  99. package/skills/article-writing/SKILL.md +79 -0
  100. package/skills/automation-audit-ops/SKILL.md +142 -0
  101. package/skills/awwwards/SKILL.md +162 -0
  102. package/skills/awwwards/metadata.json +16 -0
  103. package/skills/babylonjs-engine/SKILL.md +8 -0
  104. package/skills/backend-patterns/SKILL.md +561 -0
  105. package/skills/baqir-docs/SKILL.md +3 -0
  106. package/skills/barba-js/SKILL.md +8 -0
  107. package/skills/benchmark/SKILL.md +93 -0
  108. package/skills/best-practice/SKILL.md +7 -0
  109. package/skills/best-practice/assets/claude-memory/claude-memory-monorepo.jpg +0 -0
  110. package/skills/best-practice/assets/claude-power-ups/dial-the-model-1.png +0 -0
  111. package/skills/best-practice/assets/claude-power-ups/dial-the-model-2.png +0 -0
  112. package/skills/best-practice/assets/claude-power-ups/dial-the-model-3.png +0 -0
  113. package/skills/best-practice/assets/claude-power-ups/powerup-menu.png +0 -0
  114. package/skills/best-practice/claude-cli-startup-flags.md +231 -0
  115. package/skills/best-practice/claude-commands.md +132 -0
  116. package/skills/best-practice/claude-mcp.md +132 -0
  117. package/skills/best-practice/claude-memory.md +121 -0
  118. package/skills/best-practice/claude-power-ups.md +66 -0
  119. package/skills/best-practice/claude-settings.md +1170 -0
  120. package/skills/best-practice/claude-skills.md +58 -0
  121. package/skills/best-practice/claude-subagents.md +56 -0
  122. package/skills/blender-motion-state-inspection/SKILL.md +164 -0
  123. package/skills/bootstrap-patterns/SKILL.md +316 -0
  124. package/skills/brand-guidelines/LICENSE.txt +202 -0
  125. package/skills/brand-guidelines/SKILL.md +73 -0
  126. package/skills/brand-voice/SKILL.md +97 -0
  127. package/skills/brand-voice/references/voice-profile-schema.md +55 -0
  128. package/skills/browser-qa/SKILL.md +87 -0
  129. package/skills/canary-watch/SKILL.md +107 -0
  130. package/skills/canvas-design/LICENSE.txt +202 -0
  131. package/skills/canvas-design/SKILL.md +8 -0
  132. package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  133. package/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  134. package/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  135. package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  136. package/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  137. package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  138. package/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  139. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  140. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  141. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  142. package/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  143. package/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  144. package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  145. package/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  146. package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  147. package/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  148. package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  149. package/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  150. package/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  151. package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  152. package/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  153. package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  154. package/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  155. package/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  156. package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  157. package/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  158. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  159. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  160. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  161. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  162. package/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  163. package/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  164. package/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  165. package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  166. package/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  167. package/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  168. package/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  169. package/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  170. package/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  171. package/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  172. package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  173. package/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  174. package/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  175. package/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  176. package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  177. package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  178. package/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  179. package/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  180. package/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  181. package/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  182. package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  183. package/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  184. package/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  185. package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  186. package/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  187. package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  188. package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  189. package/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  190. package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  191. package/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  192. package/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  193. package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  194. package/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  195. package/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  196. package/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  197. package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  198. package/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  199. package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  200. package/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  201. package/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  202. package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  203. package/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  204. package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  205. package/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  206. package/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  207. package/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  208. package/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  209. package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  210. package/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  211. package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  212. package/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  213. package/skills/caveman/SKILL.md +74 -0
  214. package/skills/changelog-generator/SKILL.md +104 -0
  215. package/skills/cisco-ios-patterns/SKILL.md +163 -0
  216. package/skills/ckm:design-system/SKILL.md +3 -0
  217. package/skills/ckm:slides/SKILL.md +3 -0
  218. package/skills/claude-red/SKILL.md +35 -0
  219. package/skills/click-path-audit/SKILL.md +244 -0
  220. package/skills/clickhouse-io/SKILL.md +439 -0
  221. package/skills/codebase-onboarding/SKILL.md +233 -0
  222. package/skills/coding-standards/SKILL.md +549 -0
  223. package/skills/compose-multiplatform-patterns/SKILL.md +299 -0
  224. package/skills/computational-architecture/SKILL.md +31 -0
  225. package/skills/content-engine/SKILL.md +131 -0
  226. package/skills/content-research-writer/SKILL.md +538 -0
  227. package/skills/continuous-agent-loop/SKILL.md +45 -0
  228. package/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  229. package/skills/cpp-coding-standards/SKILL.md +723 -0
  230. package/skills/crosspost/SKILL.md +111 -0
  231. package/skills/css-container-queries/SKILL.md +132 -0
  232. package/skills/customer-billing-ops/SKILL.md +140 -0
  233. package/skills/customs-trade-compliance/SKILL.md +263 -0
  234. package/skills/dart-flutter-patterns/SKILL.md +563 -0
  235. package/skills/dashboard-builder/SKILL.md +108 -0
  236. package/skills/data-scraper-agent/SKILL.md +764 -0
  237. package/skills/database-migrations/SKILL.md +429 -0
  238. package/skills/deep-research/SKILL.md +159 -0
  239. package/skills/defi-amm-security/SKILL.md +166 -0
  240. package/skills/deployment-patterns/SKILL.md +427 -0
  241. package/skills/design-auditor/README.md +504 -0
  242. package/skills/design-auditor/README_KR.md +327 -0
  243. package/skills/design-auditor/SKILL.md +8 -0
  244. package/skills/design-auditor/references/animation.md +300 -0
  245. package/skills/design-auditor/references/color.md +241 -0
  246. package/skills/design-auditor/references/corner-radius.md +331 -0
  247. package/skills/design-auditor/references/elevation.md +249 -0
  248. package/skills/design-auditor/references/ethics.md +877 -0
  249. package/skills/design-auditor/references/figma-mcp.md +377 -0
  250. package/skills/design-auditor/references/heuristics.md +730 -0
  251. package/skills/design-auditor/references/i18n.md +254 -0
  252. package/skills/design-auditor/references/iconography.md +201 -0
  253. package/skills/design-auditor/references/microcopy.md +227 -0
  254. package/skills/design-auditor/references/navigation.md +311 -0
  255. package/skills/design-auditor/references/spacing.md +313 -0
  256. package/skills/design-auditor/references/states.md +254 -0
  257. package/skills/design-auditor/references/tokens.md +286 -0
  258. package/skills/design-auditor/references/typography.md +273 -0
  259. package/skills/design-system/SKILL.md +82 -0
  260. package/skills/design-tokens-system/SKILL.md +156 -0
  261. package/skills/development-workflows/SKILL.md +7 -0
  262. package/skills/development-workflows/cross-model-workflow/assets/cross-model-workflow.png +0 -0
  263. package/skills/development-workflows/cross-model-workflow/cross-model-workflow.md +55 -0
  264. package/skills/development-workflows/rpi/.claude/agents/code-reviewer.md +21 -0
  265. package/skills/development-workflows/rpi/.claude/agents/constitutional-validator.md +288 -0
  266. package/skills/development-workflows/rpi/.claude/agents/documentation-analyst-writer.md +64 -0
  267. package/skills/development-workflows/rpi/.claude/agents/product-manager.md +15 -0
  268. package/skills/development-workflows/rpi/.claude/agents/requirement-parser.md +238 -0
  269. package/skills/development-workflows/rpi/.claude/agents/senior-software-engineer.md +15 -0
  270. package/skills/development-workflows/rpi/.claude/agents/technical-cto-advisor.md +201 -0
  271. package/skills/development-workflows/rpi/.claude/agents/ux-designer.md +14 -0
  272. package/skills/development-workflows/rpi/.claude/commands/rpi/implement.md +634 -0
  273. package/skills/development-workflows/rpi/.claude/commands/rpi/plan.md +416 -0
  274. package/skills/development-workflows/rpi/.claude/commands/rpi/research.md +381 -0
  275. package/skills/development-workflows/rpi/rpi-workflow.md +101 -0
  276. package/skills/development-workflows/rpi/rpi-workflow.svg +178 -0
  277. package/skills/django-celery/SKILL.md +457 -0
  278. package/skills/django-patterns/SKILL.md +734 -0
  279. package/skills/django-security/SKILL.md +593 -0
  280. package/skills/django-tdd/SKILL.md +729 -0
  281. package/skills/dmux-workflows/SKILL.md +7 -0
  282. package/skills/docker-patterns/SKILL.md +364 -0
  283. package/skills/documentation-lookup/SKILL.md +90 -0
  284. package/skills/domain-name-brainstormer/SKILL.md +212 -0
  285. package/skills/dribbble/SKILL.md +160 -0
  286. package/skills/dribbble/metadata.json +16 -0
  287. package/skills/e2e-testing/SKILL.md +326 -0
  288. package/skills/empirical-research/SKILL.md +22 -0
  289. package/skills/error-handling/SKILL.md +376 -0
  290. package/skills/eval-harness/SKILL.md +270 -0
  291. package/skills/evm-token-decimals/SKILL.md +130 -0
  292. package/skills/fastapi-patterns/SKILL.md +327 -0
  293. package/skills/finance-billing-ops/SKILL.md +127 -0
  294. package/skills/flox-environments/SKILL.md +496 -0
  295. package/skills/flutter-dart-code-review/SKILL.md +435 -0
  296. package/skills/foundation-models-on-device/SKILL.md +243 -0
  297. package/skills/framer/SKILL.md +159 -0
  298. package/skills/framer/metadata.json +16 -0
  299. package/skills/frontend-design/LICENSE.txt +21 -0
  300. package/skills/frontend-design/README.md +71 -0
  301. package/skills/frontend-design/SKILL.md +115 -0
  302. package/skills/frontend-design-direction/SKILL.md +92 -0
  303. package/skills/frontend-patterns/SKILL.md +7 -0
  304. package/skills/frontend-slides/SKILL.md +184 -0
  305. package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  306. package/skills/frontend-slides/animation-patterns.md +122 -0
  307. package/skills/frontend-slides/html-template.md +419 -0
  308. package/skills/frontend-slides/scripts/export-pdf.sh +418 -0
  309. package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
  310. package/skills/frontend-slides/viewport-base.css +153 -0
  311. package/skills/gateguard/SKILL.md +125 -0
  312. package/skills/git-workflow/SKILL.md +715 -0
  313. package/skills/github-ops/SKILL.md +144 -0
  314. package/skills/golang-patterns/SKILL.md +674 -0
  315. package/skills/golang-testing/SKILL.md +720 -0
  316. package/skills/graphify/__init__.py +28 -0
  317. package/skills/graphify/__main__.py +2899 -0
  318. package/skills/graphify/analyze.py +608 -0
  319. package/skills/graphify/benchmark.py +152 -0
  320. package/skills/graphify/build.py +366 -0
  321. package/skills/graphify/cache.py +244 -0
  322. package/skills/graphify/callflow_html.py +2014 -0
  323. package/skills/graphify/cluster.py +267 -0
  324. package/skills/graphify/dedup.py +414 -0
  325. package/skills/graphify/detect.py +1018 -0
  326. package/skills/graphify/export.py +1264 -0
  327. package/skills/graphify/extract.py +6646 -0
  328. package/skills/graphify/global_graph.py +155 -0
  329. package/skills/graphify/google_workspace.py +223 -0
  330. package/skills/graphify/hooks.py +304 -0
  331. package/skills/graphify/ingest.py +331 -0
  332. package/skills/graphify/llm.py +1111 -0
  333. package/skills/graphify/manifest.py +4 -0
  334. package/skills/graphify/prs.py +746 -0
  335. package/skills/graphify/report.py +203 -0
  336. package/skills/graphify/security.py +242 -0
  337. package/skills/graphify/serve.py +899 -0
  338. package/skills/graphify/skill-aider.md +1229 -0
  339. package/skills/graphify/skill-claw.md +1229 -0
  340. package/skills/graphify/skill-codex.md +1290 -0
  341. package/skills/graphify/skill-copilot.md +1317 -0
  342. package/skills/graphify/skill-droid.md +1285 -0
  343. package/skills/graphify/skill-kiro.md +1228 -0
  344. package/skills/graphify/skill-opencode.md +1340 -0
  345. package/skills/graphify/skill-pi.md +1228 -0
  346. package/skills/graphify/skill-trae.md +1254 -0
  347. package/skills/graphify/skill-vscode.md +258 -0
  348. package/skills/graphify/skill-windows.md +1434 -0
  349. package/skills/graphify/skill.md +1086 -0
  350. package/skills/graphify/transcribe.py +184 -0
  351. package/skills/graphify/tree_html.py +580 -0
  352. package/skills/graphify/validate.py +72 -0
  353. package/skills/graphify/watch.py +728 -0
  354. package/skills/graphify/wiki.py +259 -0
  355. package/skills/growth-marketing/SKILL.md +26 -0
  356. package/skills/gsap-scrolltrigger/SKILL.md +8 -0
  357. package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
  358. package/skills/healthcare-emr-patterns/SKILL.md +159 -0
  359. package/skills/healthcare-phi-compliance/SKILL.md +145 -0
  360. package/skills/hexagonal-architecture/SKILL.md +276 -0
  361. package/skills/hipaa-compliance/SKILL.md +78 -0
  362. package/skills/homelab-network-setup/SKILL.md +129 -0
  363. package/skills/imhcode/SKILL.md +183 -0
  364. package/skills/imhcode-brainstorm/SKILL.md +37 -0
  365. package/skills/imhcode-codebase-knowledge/SKILL.md +37 -0
  366. package/skills/imhcode-codebase-knowledge/assets/templates/ARCHITECTURE.md +49 -0
  367. package/skills/imhcode-codebase-knowledge/assets/templates/CONCERNS.md +56 -0
  368. package/skills/imhcode-codebase-knowledge/assets/templates/CONVENTIONS.md +52 -0
  369. package/skills/imhcode-codebase-knowledge/assets/templates/INTEGRATIONS.md +48 -0
  370. package/skills/imhcode-codebase-knowledge/assets/templates/STACK.md +56 -0
  371. package/skills/imhcode-codebase-knowledge/assets/templates/STRUCTURE.md +44 -0
  372. package/skills/imhcode-codebase-knowledge/assets/templates/TESTING.md +57 -0
  373. package/skills/imhcode-codebase-knowledge/references/inquiry-checkpoints.md +70 -0
  374. package/skills/imhcode-codebase-knowledge/references/stack-detection.md +131 -0
  375. package/skills/imhcode-codebase-knowledge/scripts/scan.py +712 -0
  376. package/skills/imhcode-dispatch/SKILL.md +31 -0
  377. package/skills/imhcode-saas-architect/SKILL.md +55 -0
  378. package/skills/imhcode-security/SKILL.md +42 -0
  379. package/skills/imhcode-sprint-planner/SKILL.md +42 -0
  380. package/skills/inventory-demand-planning/SKILL.md +247 -0
  381. package/skills/investor-materials/SKILL.md +96 -0
  382. package/skills/investor-outreach/SKILL.md +91 -0
  383. package/skills/ios-icon-gen/SKILL.md +157 -0
  384. package/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
  385. package/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
  386. package/skills/java-coding-standards/SKILL.md +383 -0
  387. package/skills/jpa-patterns/SKILL.md +151 -0
  388. package/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  389. package/skills/kotlin-patterns/SKILL.md +711 -0
  390. package/skills/laravel-patterns/SKILL.md +415 -0
  391. package/skills/laravel-plugin-discovery/SKILL.md +229 -0
  392. package/skills/laravel-security/SKILL.md +285 -0
  393. package/skills/laravel-tdd/SKILL.md +283 -0
  394. package/skills/laravel-verification/SKILL.md +179 -0
  395. package/skills/lightweight-3d-effects/SKILL.md +8 -0
  396. package/skills/linear/SKILL.md +156 -0
  397. package/skills/linear/metadata.json +16 -0
  398. package/skills/liquid-glass-design/SKILL.md +279 -0
  399. package/skills/llm-trading-agent-security/SKILL.md +146 -0
  400. package/skills/locomotive-scroll/SKILL.md +8 -0
  401. package/skills/logistics-exception-management/SKILL.md +222 -0
  402. package/skills/lottie-animations/SKILL.md +8 -0
  403. package/skills/make-interfaces-feel-better/SKILL.md +151 -0
  404. package/skills/mcp-server-patterns/SKILL.md +69 -0
  405. package/skills/meeting-insights-analyzer/SKILL.md +327 -0
  406. package/skills/micro-interactions/SKILL.md +178 -0
  407. package/skills/mle-workflow/SKILL.md +346 -0
  408. package/skills/mobbin/SKILL.md +157 -0
  409. package/skills/mobbin/metadata.json +16 -0
  410. package/skills/mobile-app-design/README.md +302 -0
  411. package/skills/mobile-app-design/SKILL.md +330 -0
  412. package/skills/mobile-app-design/examples/design-system-config.ts +685 -0
  413. package/skills/mobile-app-design/examples/form-validation-example.tsx +501 -0
  414. package/skills/mobile-app-design/examples/optimized-list-example.tsx +384 -0
  415. package/skills/mobile-app-design/examples/profile-screen-example.tsx +450 -0
  416. package/skills/mobile-app-design/references/accessibility-checklist.md +525 -0
  417. package/skills/mobile-app-design/references/android-guidelines.md +582 -0
  418. package/skills/mobile-app-design/references/common-mistakes.md +834 -0
  419. package/skills/mobile-app-design/references/ios-guidelines.md +421 -0
  420. package/skills/mobile-app-design/references/performance-patterns.md +705 -0
  421. package/skills/mobile-app-design/references/platform-differences.md +353 -0
  422. package/skills/mobile-app-design/references/ui-libraries.md +729 -0
  423. package/skills/mobile-app-design/scripts/accessibility-audit.sh +281 -0
  424. package/skills/mobile-app-design/scripts/check-contrast.py +188 -0
  425. package/skills/mobile-app-design/scripts/validate-touch-targets.sh +228 -0
  426. package/skills/mobile-app-ui-design/INDEX.md +131 -0
  427. package/skills/mobile-app-ui-design/README.md +135 -0
  428. package/skills/mobile-app-ui-design/SKILL.md +7 -0
  429. package/skills/mobile-app-ui-design/references/industry-conventions.md +151 -0
  430. package/skills/modern-web-design/SKILL.md +8 -0
  431. package/skills/motion-advanced/SKILL.md +596 -0
  432. package/skills/motion-design/SKILL.md +21 -0
  433. package/skills/motion-foundations/SKILL.md +299 -0
  434. package/skills/motion-framer/SKILL.md +8 -0
  435. package/skills/motion-patterns/SKILL.md +435 -0
  436. package/skills/motion-ui/SKILL.md +575 -0
  437. package/skills/mysql-patterns/SKILL.md +412 -0
  438. package/skills/nestjs-patterns/SKILL.md +230 -0
  439. package/skills/network-config-validation/SKILL.md +210 -0
  440. package/skills/nextjs-turbopack/SKILL.md +44 -0
  441. package/skills/nodejs-keccak256/SKILL.md +102 -0
  442. package/skills/nothing-design/SKILL.md +177 -0
  443. package/skills/nothing-design/references/components.md +153 -0
  444. package/skills/nothing-design/references/platform-mapping.md +64 -0
  445. package/skills/nothing-design/references/tokens.md +142 -0
  446. package/skills/nuxt4-patterns/SKILL.md +100 -0
  447. package/skills/openclaw-persona-forge/SKILL.md +288 -0
  448. package/skills/openclaw-persona-forge/gacha.py +224 -0
  449. package/skills/openclaw-persona-forge/gacha.sh +5 -0
  450. package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
  451. package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
  452. package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
  453. package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
  454. package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
  455. package/skills/openclaw-persona-forge/references/output-template.md +166 -0
  456. package/skills/orchestration-workflow/SKILL.md +199 -0
  457. package/skills/orchestration-workflow/orchestration-workflow.gif +0 -0
  458. package/skills/orchestration-workflow/orchestration-workflow.md +199 -0
  459. package/skills/orchestration-workflow/orchestration-workflow.svg +78 -0
  460. package/skills/orchestration-workflow/output.md +13 -0
  461. package/skills/orchestration-workflow/weather.svg +6 -0
  462. package/skills/pixijs-2d/SKILL.md +8 -0
  463. package/skills/plan-orchestrate/SKILL.md +262 -0
  464. package/skills/plankton-code-quality/SKILL.md +236 -0
  465. package/skills/postgres-patterns/SKILL.md +147 -0
  466. package/skills/ppt-mckinsey/SKILL.md +27 -0
  467. package/skills/prisma-patterns/SKILL.md +371 -0
  468. package/skills/product-capability/SKILL.md +141 -0
  469. package/skills/product-lens/SKILL.md +92 -0
  470. package/skills/production-audit/SKILL.md +206 -0
  471. package/skills/project-flow-ops/SKILL.md +111 -0
  472. package/skills/prompt-optimizer/SKILL.md +398 -0
  473. package/skills/python-patterns/SKILL.md +750 -0
  474. package/skills/python-testing/SKILL.md +816 -0
  475. package/skills/pytorch-patterns/SKILL.md +396 -0
  476. package/skills/quarkus-patterns/SKILL.md +722 -0
  477. package/skills/radix-ui-primitives/SKILL.md +86 -0
  478. package/skills/react-native-best-practices/SKILL.md +83 -0
  479. package/skills/react-native-brownfield-migration/SKILL.md +115 -0
  480. package/skills/react-spring-physics/SKILL.md +8 -0
  481. package/skills/react-three-fiber/SKILL.md +8 -0
  482. package/skills/recsys-pipeline-architect/SKILL.md +114 -0
  483. package/skills/redis-patterns/SKILL.md +403 -0
  484. package/skills/remotion-video-creation/SKILL.md +43 -0
  485. package/skills/remotion-video-creation/rules/3d.md +86 -0
  486. package/skills/remotion-video-creation/rules/animations.md +29 -0
  487. package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
  488. package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
  489. package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
  490. package/skills/remotion-video-creation/rules/assets.md +78 -0
  491. package/skills/remotion-video-creation/rules/audio.md +172 -0
  492. package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
  493. package/skills/remotion-video-creation/rules/can-decode.md +75 -0
  494. package/skills/remotion-video-creation/rules/charts.md +58 -0
  495. package/skills/remotion-video-creation/rules/compositions.md +146 -0
  496. package/skills/remotion-video-creation/rules/display-captions.md +126 -0
  497. package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
  498. package/skills/remotion-video-creation/rules/fonts.md +152 -0
  499. package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
  500. package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
  501. package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
  502. package/skills/remotion-video-creation/rules/gifs.md +138 -0
  503. package/skills/remotion-video-creation/rules/images.md +130 -0
  504. package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
  505. package/skills/remotion-video-creation/rules/lottie.md +67 -0
  506. package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
  507. package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
  508. package/skills/remotion-video-creation/rules/sequencing.md +106 -0
  509. package/skills/remotion-video-creation/rules/tailwind.md +11 -0
  510. package/skills/remotion-video-creation/rules/text-animations.md +20 -0
  511. package/skills/remotion-video-creation/rules/timing.md +179 -0
  512. package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
  513. package/skills/remotion-video-creation/rules/transitions.md +122 -0
  514. package/skills/remotion-video-creation/rules/trimming.md +52 -0
  515. package/skills/remotion-video-creation/rules/videos.md +171 -0
  516. package/skills/repo-scan/SKILL.md +78 -0
  517. package/skills/responsive-email-templates/SKILL.md +110 -0
  518. package/skills/rive-interactive/SKILL.md +8 -0
  519. package/skills/rust-patterns/SKILL.md +499 -0
  520. package/skills/rust-testing/SKILL.md +500 -0
  521. package/skills/scroll-reveal-libraries/SKILL.md +8 -0
  522. package/skills/security-bounty-hunter/SKILL.md +99 -0
  523. package/skills/security-review/SKILL.md +503 -0
  524. package/skills/security-review/cloud-infrastructure-security.md +361 -0
  525. package/skills/security-scan/SKILL.md +165 -0
  526. package/skills/seo/SKILL.md +154 -0
  527. package/skills/seo-growth/SKILL.md +34 -0
  528. package/skills/shadcn-ui-patterns/SKILL.md +123 -0
  529. package/skills/spline-interactive/SKILL.md +8 -0
  530. package/skills/springboot-patterns/SKILL.md +314 -0
  531. package/skills/springboot-security/SKILL.md +272 -0
  532. package/skills/springboot-tdd/SKILL.md +158 -0
  533. package/skills/strategic-compact/SKILL.md +131 -0
  534. package/skills/stripe/SKILL.md +168 -0
  535. package/skills/stripe/metadata.json +16 -0
  536. package/skills/swift-actor-persistence/SKILL.md +143 -0
  537. package/skills/swift-concurrency-6-2/SKILL.md +216 -0
  538. package/skills/swiftui-patterns/SKILL.md +259 -0
  539. package/skills/systematic-debugging/CREATION-LOG.md +119 -0
  540. package/skills/systematic-debugging/SKILL.md +296 -0
  541. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  542. package/skills/systematic-debugging/condition-based-waiting.md +115 -0
  543. package/skills/systematic-debugging/defense-in-depth.md +122 -0
  544. package/skills/systematic-debugging/find-polluter.sh +63 -0
  545. package/skills/systematic-debugging/root-cause-tracing.md +169 -0
  546. package/skills/systematic-debugging/test-academic.md +14 -0
  547. package/skills/systematic-debugging/test-pressure-1.md +58 -0
  548. package/skills/systematic-debugging/test-pressure-2.md +68 -0
  549. package/skills/systematic-debugging/test-pressure-3.md +69 -0
  550. package/skills/tailwindcss-v4/SKILL.md +107 -0
  551. package/skills/tdd-workflow/SKILL.md +463 -0
  552. package/skills/team-builder/SKILL.md +168 -0
  553. package/skills/test-driven-development/SKILL.md +371 -0
  554. package/skills/test-driven-development/testing-anti-patterns.md +299 -0
  555. package/skills/theme-factory/LICENSE.txt +202 -0
  556. package/skills/theme-factory/SKILL.md +59 -0
  557. package/skills/theme-factory/theme-showcase.pdf +0 -0
  558. package/skills/theme-factory/themes/arctic-frost.md +19 -0
  559. package/skills/theme-factory/themes/botanical-garden.md +19 -0
  560. package/skills/theme-factory/themes/desert-rose.md +19 -0
  561. package/skills/theme-factory/themes/forest-canopy.md +19 -0
  562. package/skills/theme-factory/themes/golden-hour.md +19 -0
  563. package/skills/theme-factory/themes/midnight-galaxy.md +19 -0
  564. package/skills/theme-factory/themes/modern-minimalist.md +19 -0
  565. package/skills/theme-factory/themes/ocean-depths.md +19 -0
  566. package/skills/theme-factory/themes/sunset-boulevard.md +19 -0
  567. package/skills/theme-factory/themes/tech-innovation.md +19 -0
  568. package/skills/threejs-webgl/SKILL.md +8 -0
  569. package/skills/trailofbits-auditing/SKILL.md +30 -0
  570. package/skills/twitter-algorithm-optimizer/SKILL.md +327 -0
  571. package/skills/typeui-cli/SKILL.md +90 -0
  572. package/skills/typeui-main/DESIGN.md +114 -0
  573. package/skills/typeui-main/LICENSE.md +9 -0
  574. package/skills/typeui-main/README.md +84 -0
  575. package/skills/typeui-main/REGISTRY.md +60 -0
  576. package/skills/typeui-main/SKILL.md +114 -0
  577. package/skills/typeui-main/package-lock.json +2123 -0
  578. package/skills/typeui-main/package.json +56 -0
  579. package/skills/typeui-main/skills/typeui-cli/SKILL.md +90 -0
  580. package/skills/typeui-main/src/cli.ts +282 -0
  581. package/skills/typeui-main/src/config.ts +28 -0
  582. package/skills/typeui-main/src/domain/designSystemSchema.ts +77 -0
  583. package/skills/typeui-main/src/generation/existingDesignSystem.ts +228 -0
  584. package/skills/typeui-main/src/generation/randomDesignSystem.ts +348 -0
  585. package/skills/typeui-main/src/generation/runDesignGeneration.ts +31 -0
  586. package/skills/typeui-main/src/generation/runGeneration.ts +36 -0
  587. package/skills/typeui-main/src/generation/runPull.ts +62 -0
  588. package/skills/typeui-main/src/io/updateSkillFile.ts +118 -0
  589. package/skills/typeui-main/src/prompts/designSystem.ts +755 -0
  590. package/skills/typeui-main/src/prompts/registry.ts +72 -0
  591. package/skills/typeui-main/src/registry/registryClient.ts +246 -0
  592. package/skills/typeui-main/src/renderers/claudeRenderer.ts +10 -0
  593. package/skills/typeui-main/src/renderers/codexRenderer.ts +10 -0
  594. package/skills/typeui-main/src/renderers/cursorRenderer.ts +10 -0
  595. package/skills/typeui-main/src/renderers/index.ts +14 -0
  596. package/skills/typeui-main/src/renderers/openCodeRenderer.ts +10 -0
  597. package/skills/typeui-main/src/renderers/shared.ts +252 -0
  598. package/skills/typeui-main/src/skillMetadata.ts +19 -0
  599. package/skills/typeui-main/src/types.ts +204 -0
  600. package/skills/typeui-main/src/ui/banner.ts +20 -0
  601. package/skills/typeui-main/test/existingDesignSystem.test.ts +67 -0
  602. package/skills/typeui-main/test/orchestrator.test.ts +113 -0
  603. package/skills/typeui-main/test/randomDesignSystem.test.ts +20 -0
  604. package/skills/typeui-main/test/registryClient.test.ts +408 -0
  605. package/skills/typeui-main/test/renderers.test.ts +41 -0
  606. package/skills/typeui-main/test/runDesignGeneration.test.ts +52 -0
  607. package/skills/typeui-main/test/runPull.test.ts +92 -0
  608. package/skills/typeui-main/test/skillMetadata.test.ts +11 -0
  609. package/skills/typeui-main/test/updateSkillFile.test.ts +160 -0
  610. package/skills/typeui-main/tsconfig.json +16 -0
  611. package/skills/ui-demo/SKILL.md +465 -0
  612. package/skills/ui-to-vue/SKILL.md +134 -0
  613. package/skills/ui-ux-pro-max/.claude/skills/banner-design/SKILL.md +192 -0
  614. package/skills/ui-ux-pro-max/.claude/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
  615. package/skills/ui-ux-pro-max/.claude/skills/brand/SKILL.md +97 -0
  616. package/skills/ui-ux-pro-max/.claude/skills/brand/references/approval-checklist.md +169 -0
  617. package/skills/ui-ux-pro-max/.claude/skills/brand/references/asset-organization.md +157 -0
  618. package/skills/ui-ux-pro-max/.claude/skills/brand/references/brand-guideline-template.md +140 -0
  619. package/skills/ui-ux-pro-max/.claude/skills/brand/references/color-palette-management.md +186 -0
  620. package/skills/ui-ux-pro-max/.claude/skills/brand/references/consistency-checklist.md +94 -0
  621. package/skills/ui-ux-pro-max/.claude/skills/brand/references/logo-usage-rules.md +185 -0
  622. package/skills/ui-ux-pro-max/.claude/skills/brand/references/messaging-framework.md +85 -0
  623. package/skills/ui-ux-pro-max/.claude/skills/brand/references/typography-specifications.md +214 -0
  624. package/skills/ui-ux-pro-max/.claude/skills/brand/references/update.md +118 -0
  625. package/skills/ui-ux-pro-max/.claude/skills/brand/references/visual-identity.md +96 -0
  626. package/skills/ui-ux-pro-max/.claude/skills/brand/references/voice-framework.md +88 -0
  627. package/skills/ui-ux-pro-max/.claude/skills/brand/scripts/extract-colors.cjs +341 -0
  628. package/skills/ui-ux-pro-max/.claude/skills/brand/scripts/inject-brand-context.cjs +349 -0
  629. package/skills/ui-ux-pro-max/.claude/skills/brand/scripts/sync-brand-to-tokens.cjs +266 -0
  630. package/skills/ui-ux-pro-max/.claude/skills/brand/scripts/validate-asset.cjs +387 -0
  631. package/skills/ui-ux-pro-max/.claude/skills/brand/templates/brand-guidelines-starter.md +275 -0
  632. package/skills/ui-ux-pro-max/.claude/skills/design/SKILL.md +302 -0
  633. package/skills/ui-ux-pro-max/.claude/skills/design/data/cip/deliverables.csv +51 -0
  634. package/skills/ui-ux-pro-max/.claude/skills/design/data/cip/industries.csv +21 -0
  635. package/skills/ui-ux-pro-max/.claude/skills/design/data/cip/mockup-contexts.csv +21 -0
  636. package/skills/ui-ux-pro-max/.claude/skills/design/data/cip/styles.csv +21 -0
  637. package/skills/ui-ux-pro-max/.claude/skills/design/data/icon/styles.csv +16 -0
  638. package/skills/ui-ux-pro-max/.claude/skills/design/data/logo/colors.csv +56 -0
  639. package/skills/ui-ux-pro-max/.claude/skills/design/data/logo/industries.csv +56 -0
  640. package/skills/ui-ux-pro-max/.claude/skills/design/data/logo/styles.csv +56 -0
  641. package/skills/ui-ux-pro-max/.claude/skills/design/references/banner-sizes-and-styles.md +118 -0
  642. package/skills/ui-ux-pro-max/.claude/skills/design/references/cip-deliverable-guide.md +95 -0
  643. package/skills/ui-ux-pro-max/.claude/skills/design/references/cip-design.md +121 -0
  644. package/skills/ui-ux-pro-max/.claude/skills/design/references/cip-prompt-engineering.md +84 -0
  645. package/skills/ui-ux-pro-max/.claude/skills/design/references/cip-style-guide.md +68 -0
  646. package/skills/ui-ux-pro-max/.claude/skills/design/references/design-routing.md +207 -0
  647. package/skills/ui-ux-pro-max/.claude/skills/design/references/icon-design.md +122 -0
  648. package/skills/ui-ux-pro-max/.claude/skills/design/references/logo-color-psychology.md +101 -0
  649. package/skills/ui-ux-pro-max/.claude/skills/design/references/logo-design.md +92 -0
  650. package/skills/ui-ux-pro-max/.claude/skills/design/references/logo-prompt-engineering.md +158 -0
  651. package/skills/ui-ux-pro-max/.claude/skills/design/references/logo-style-guide.md +109 -0
  652. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides-copywriting-formulas.md +84 -0
  653. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides-create.md +4 -0
  654. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides-html-template.md +295 -0
  655. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides-layout-patterns.md +137 -0
  656. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides-strategies.md +94 -0
  657. package/skills/ui-ux-pro-max/.claude/skills/design/references/slides.md +42 -0
  658. package/skills/ui-ux-pro-max/.claude/skills/design/references/social-photos-design.md +329 -0
  659. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/cip/core.py +215 -0
  660. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/cip/generate.py +484 -0
  661. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/cip/render-html.py +424 -0
  662. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/cip/search.py +127 -0
  663. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/icon/generate.py +487 -0
  664. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/logo/core.py +175 -0
  665. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/logo/generate.py +362 -0
  666. package/skills/ui-ux-pro-max/.claude/skills/design/scripts/logo/search.py +114 -0
  667. package/skills/ui-ux-pro-max/.claude/skills/design-system/SKILL.md +244 -0
  668. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-backgrounds.csv +11 -0
  669. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-charts.csv +26 -0
  670. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-color-logic.csv +14 -0
  671. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-copy.csv +26 -0
  672. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-layout-logic.csv +16 -0
  673. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-layouts.csv +26 -0
  674. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-strategies.csv +16 -0
  675. package/skills/ui-ux-pro-max/.claude/skills/design-system/data/slide-typography.csv +15 -0
  676. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/component-specs.md +236 -0
  677. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/component-tokens.md +214 -0
  678. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/primitive-tokens.md +203 -0
  679. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/semantic-tokens.md +215 -0
  680. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/states-and-variants.md +241 -0
  681. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/tailwind-integration.md +251 -0
  682. package/skills/ui-ux-pro-max/.claude/skills/design-system/references/token-architecture.md +224 -0
  683. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/embed-tokens.cjs +99 -0
  684. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/fetch-background.py +317 -0
  685. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/generate-slide.py +753 -0
  686. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/generate-tokens.cjs +205 -0
  687. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/html-token-validator.py +327 -0
  688. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/search-slides.py +218 -0
  689. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/slide-token-validator.py +35 -0
  690. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/slide_search_core.py +453 -0
  691. package/skills/ui-ux-pro-max/.claude/skills/design-system/scripts/validate-tokens.cjs +251 -0
  692. package/skills/ui-ux-pro-max/.claude/skills/design-system/templates/design-tokens-starter.json +143 -0
  693. package/skills/ui-ux-pro-max/.claude/skills/slides/SKILL.md +42 -0
  694. package/skills/ui-ux-pro-max/.claude/skills/slides/references/copywriting-formulas.md +84 -0
  695. package/skills/ui-ux-pro-max/.claude/skills/slides/references/create.md +4 -0
  696. package/skills/ui-ux-pro-max/.claude/skills/slides/references/html-template.md +295 -0
  697. package/skills/ui-ux-pro-max/.claude/skills/slides/references/layout-patterns.md +137 -0
  698. package/skills/ui-ux-pro-max/.claude/skills/slides/references/slide-strategies.md +94 -0
  699. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/LICENSE.txt +202 -0
  700. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/SKILL.md +324 -0
  701. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  702. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  703. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  704. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  705. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  706. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  707. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  708. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  709. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  710. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  711. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  712. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  713. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  714. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  715. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  716. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  717. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  718. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  719. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  720. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  721. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  722. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  723. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  724. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  725. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  726. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  727. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  728. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  729. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  730. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  731. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  732. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  733. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  734. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  735. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  736. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  737. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  738. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  739. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  740. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  741. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  742. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  743. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  744. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  745. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  746. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  747. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  748. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  749. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  750. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  751. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  752. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  753. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  754. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  755. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  756. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  757. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  758. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  759. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  760. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  761. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  762. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  763. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  764. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  765. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  766. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  767. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  768. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  769. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  770. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  771. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  772. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  773. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  774. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  775. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  776. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  777. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  778. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  779. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  780. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  781. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  782. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/canvas-design-system.md +320 -0
  783. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/shadcn-accessibility.md +471 -0
  784. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/shadcn-components.md +424 -0
  785. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/shadcn-theming.md +373 -0
  786. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/tailwind-customization.md +483 -0
  787. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/tailwind-responsive.md +382 -0
  788. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/references/tailwind-utilities.md +455 -0
  789. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/.coverage +0 -0
  790. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/requirements.txt +17 -0
  791. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/shadcn_add.py +292 -0
  792. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
  793. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/tests/coverage-ui.json +1 -0
  794. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/tests/requirements.txt +3 -0
  795. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  796. package/skills/ui-ux-pro-max/.claude/skills/ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
  797. package/skills/ui-ux-pro-max/.claude/skills/ui-ux-pro-max/SKILL.md +659 -0
  798. package/skills/ui-ux-pro-max/.claude-plugin/marketplace.json +35 -0
  799. package/skills/ui-ux-pro-max/.claude-plugin/plugin.json +11 -0
  800. package/skills/ui-ux-pro-max/.github/workflows/claude-code-review.yml +44 -0
  801. package/skills/ui-ux-pro-max/.github/workflows/claude.yml +50 -0
  802. package/skills/ui-ux-pro-max/.github/workflows/python-package-conda.yml +34 -0
  803. package/skills/ui-ux-pro-max/CLAUDE.md +98 -0
  804. package/skills/ui-ux-pro-max/LICENSE +21 -0
  805. package/skills/ui-ux-pro-max/README.md +513 -0
  806. package/skills/ui-ux-pro-max/SKILL.md +292 -0
  807. package/skills/ui-ux-pro-max/cli/README.md +63 -0
  808. package/skills/ui-ux-pro-max/cli/assets/data/_sync_all.py +414 -0
  809. package/skills/ui-ux-pro-max/cli/assets/data/app-interface.csv +31 -0
  810. package/skills/ui-ux-pro-max/cli/assets/data/charts.csv +26 -0
  811. package/skills/ui-ux-pro-max/cli/assets/data/colors.csv +162 -0
  812. package/skills/ui-ux-pro-max/cli/assets/data/design.csv +1776 -0
  813. package/skills/ui-ux-pro-max/cli/assets/data/draft.csv +1779 -0
  814. package/skills/ui-ux-pro-max/cli/assets/data/google-fonts.csv +1924 -0
  815. package/skills/ui-ux-pro-max/cli/assets/data/icons.csv +105 -0
  816. package/skills/ui-ux-pro-max/cli/assets/data/landing.csv +31 -0
  817. package/skills/ui-ux-pro-max/cli/assets/data/products.csv +162 -0
  818. package/skills/ui-ux-pro-max/cli/assets/data/react-performance.csv +45 -0
  819. package/skills/ui-ux-pro-max/cli/assets/data/stacks/angular.csv +51 -0
  820. package/skills/ui-ux-pro-max/cli/assets/data/stacks/astro.csv +54 -0
  821. package/skills/ui-ux-pro-max/cli/assets/data/stacks/flutter.csv +53 -0
  822. package/skills/ui-ux-pro-max/cli/assets/data/stacks/html-tailwind.csv +56 -0
  823. package/skills/ui-ux-pro-max/cli/assets/data/stacks/jetpack-compose.csv +53 -0
  824. package/skills/ui-ux-pro-max/cli/assets/data/stacks/laravel.csv +51 -0
  825. package/skills/ui-ux-pro-max/cli/assets/data/stacks/nextjs.csv +53 -0
  826. package/skills/ui-ux-pro-max/cli/assets/data/stacks/nuxt-ui.csv +51 -0
  827. package/skills/ui-ux-pro-max/cli/assets/data/stacks/nuxtjs.csv +59 -0
  828. package/skills/ui-ux-pro-max/cli/assets/data/stacks/react-native.csv +52 -0
  829. package/skills/ui-ux-pro-max/cli/assets/data/stacks/react.csv +54 -0
  830. package/skills/ui-ux-pro-max/cli/assets/data/stacks/shadcn.csv +61 -0
  831. package/skills/ui-ux-pro-max/cli/assets/data/stacks/svelte.csv +54 -0
  832. package/skills/ui-ux-pro-max/cli/assets/data/stacks/swiftui.csv +51 -0
  833. package/skills/ui-ux-pro-max/cli/assets/data/stacks/threejs.csv +54 -0
  834. package/skills/ui-ux-pro-max/cli/assets/data/stacks/vue.csv +50 -0
  835. package/skills/ui-ux-pro-max/cli/assets/data/styles.csv +85 -0
  836. package/skills/ui-ux-pro-max/cli/assets/data/typography.csv +74 -0
  837. package/skills/ui-ux-pro-max/cli/assets/data/ui-reasoning.csv +162 -0
  838. package/skills/ui-ux-pro-max/cli/assets/data/ux-guidelines.csv +100 -0
  839. package/skills/ui-ux-pro-max/cli/assets/scripts/core.py +247 -0
  840. package/skills/ui-ux-pro-max/cli/assets/scripts/design_system.py +1148 -0
  841. package/skills/ui-ux-pro-max/cli/assets/scripts/search.py +114 -0
  842. package/skills/ui-ux-pro-max/cli/assets/templates/base/quick-reference.md +297 -0
  843. package/skills/ui-ux-pro-max/cli/assets/templates/base/skill-content.md +353 -0
  844. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/agent.json +21 -0
  845. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/augment.json +18 -0
  846. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/claude.json +21 -0
  847. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/codebuddy.json +21 -0
  848. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/codex.json +21 -0
  849. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/continue.json +21 -0
  850. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/copilot.json +21 -0
  851. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/cursor.json +21 -0
  852. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/droid.json +21 -0
  853. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/gemini.json +21 -0
  854. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/kilocode.json +21 -0
  855. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/kiro.json +21 -0
  856. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/opencode.json +21 -0
  857. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/qoder.json +21 -0
  858. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/roocode.json +21 -0
  859. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/trae.json +21 -0
  860. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/warp.json +18 -0
  861. package/skills/ui-ux-pro-max/cli/assets/templates/platforms/windsurf.json +21 -0
  862. package/skills/ui-ux-pro-max/cli/bun.lock +77 -0
  863. package/skills/ui-ux-pro-max/cli/package-lock.json +370 -0
  864. package/skills/ui-ux-pro-max/cli/package.json +48 -0
  865. package/skills/ui-ux-pro-max/cli/src/commands/init.ts +216 -0
  866. package/skills/ui-ux-pro-max/cli/src/commands/uninstall.ts +135 -0
  867. package/skills/ui-ux-pro-max/cli/src/commands/update.ts +36 -0
  868. package/skills/ui-ux-pro-max/cli/src/commands/versions.ts +42 -0
  869. package/skills/ui-ux-pro-max/cli/src/index.ts +83 -0
  870. package/skills/ui-ux-pro-max/cli/src/types/index.ts +68 -0
  871. package/skills/ui-ux-pro-max/cli/src/utils/detect.ts +120 -0
  872. package/skills/ui-ux-pro-max/cli/src/utils/extract.ts +149 -0
  873. package/skills/ui-ux-pro-max/cli/src/utils/github.ts +104 -0
  874. package/skills/ui-ux-pro-max/cli/src/utils/logger.ts +11 -0
  875. package/skills/ui-ux-pro-max/cli/src/utils/template.ts +243 -0
  876. package/skills/ui-ux-pro-max/cli/tsconfig.json +17 -0
  877. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  878. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  879. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  880. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  881. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  882. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  883. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  884. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  885. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  886. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  887. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  888. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  889. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  890. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  891. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  892. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  893. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  894. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  895. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  896. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  897. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  898. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  899. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  900. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  901. package/skills/ui-ux-pro-max/docs//344/270/211/344/270/252 data-scripts-templates /347/232/204/345/214/272/345/210/253.md" +30 -0
  902. package/skills/ui-ux-pro-max/preview/xiaomaomi-app.html +411 -0
  903. package/skills/ui-ux-pro-max/screenshots/website.png +0 -0
  904. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  905. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  906. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  907. package/skills/ui-ux-pro-max/skill.json +41 -0
  908. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/_sync_all.py +414 -0
  909. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/app-interface.csv +31 -0
  910. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/charts.csv +26 -0
  911. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/colors.csv +162 -0
  912. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/design.csv +1776 -0
  913. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/draft.csv +1779 -0
  914. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/google-fonts.csv +1924 -0
  915. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/icons.csv +106 -0
  916. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/landing.csv +35 -0
  917. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/products.csv +162 -0
  918. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/react-performance.csv +45 -0
  919. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/angular.csv +51 -0
  920. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  921. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  922. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  923. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  924. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/laravel.csv +51 -0
  925. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  926. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  927. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  928. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  929. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/react.csv +54 -0
  930. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  931. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  932. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  933. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/threejs.csv +54 -0
  934. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  935. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/styles.csv +85 -0
  936. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/typography.csv +74 -0
  937. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
  938. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  939. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/scripts/core.py +262 -0
  940. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/scripts/design_system.py +1148 -0
  941. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/scripts/search.py +114 -0
  942. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/base/quick-reference.md +297 -0
  943. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/base/skill-content.md +358 -0
  944. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/agent.json +21 -0
  945. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/augment.json +18 -0
  946. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/claude.json +21 -0
  947. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/codebuddy.json +21 -0
  948. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/codex.json +21 -0
  949. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/continue.json +21 -0
  950. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/copilot.json +21 -0
  951. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/cursor.json +21 -0
  952. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/droid.json +21 -0
  953. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/gemini.json +21 -0
  954. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/kilocode.json +21 -0
  955. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/kiro.json +21 -0
  956. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/opencode.json +21 -0
  957. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/qoder.json +21 -0
  958. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/roocode.json +21 -0
  959. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/trae.json +21 -0
  960. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/warp.json +18 -0
  961. package/skills/ui-ux-pro-max/src/ui-ux-pro-max/templates/platforms/windsurf.json +21 -0
  962. package/skills/uncloud/SKILL.md +343 -0
  963. package/skills/upgrading-react-native/SKILL.md +58 -0
  964. package/skills/using-git-worktrees/SKILL.md +215 -0
  965. package/skills/vercel/SKILL.md +161 -0
  966. package/skills/vercel/metadata.json +16 -0
  967. package/skills/verification-loop/SKILL.md +126 -0
  968. package/skills/view-transitions-api/SKILL.md +108 -0
  969. package/skills/vite-patterns/SKILL.md +449 -0
  970. package/skills/vue3-composition-patterns/SKILL.md +375 -0
  971. package/skills/waza-habits/SKILL.md +22 -0
  972. package/skills/webapp-testing/LICENSE.txt +202 -0
  973. package/skills/webapp-testing/SKILL.md +96 -0
  974. package/skills/webapp-testing/examples/console_logging.py +35 -0
  975. package/skills/webapp-testing/examples/element_discovery.py +40 -0
  976. package/skills/webapp-testing/examples/static_html_automation.py +33 -0
  977. package/skills/webapp-testing/scripts/with_server.py +106 -0
  978. package/src/orchestrator/builder.ts +234 -0
  979. package/src/orchestrator/executor.ts +386 -0
  980. package/src/orchestrator/index.ts +535 -0
  981. package/src/orchestrator/loader.ts +237 -0
  982. package/src/orchestrator/registry.ts +211 -0
  983. package/src/orchestrator/schema.ts +141 -0
  984. package/src/orchestrator/session.ts +128 -0
  985. package/src/orchestrator/types.ts +109 -0
  986. package/tsconfig.json +21 -0
@@ -0,0 +1,1018 @@
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
+ from enum import Enum
8
+ from pathlib import Path
9
+
10
+ from graphify.google_workspace import (
11
+ GOOGLE_WORKSPACE_EXTENSIONS,
12
+ convert_google_workspace_file,
13
+ google_workspace_enabled,
14
+ )
15
+
16
+
17
+ class FileType(str, Enum):
18
+ CODE = "code"
19
+ DOCUMENT = "document"
20
+ PAPER = "paper"
21
+ IMAGE = "image"
22
+ VIDEO = "video"
23
+
24
+
25
+ _MANIFEST_PATH = "graphify-out/manifest.json"
26
+
27
+ CODE_EXTENSIONS = {'.py', '.ts', '.js', '.jsx', '.tsx', '.mjs', '.ejs', '.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', '.sql', '.r', '.f', '.F', '.f90', '.F90', '.f95', '.F95', '.f03', '.F03', '.f08', '.F08', '.pas', '.pp', '.dpr', '.dpk', '.lpr', '.inc', '.dfm', '.lfm', '.lpk', '.sh', '.bash', '.json'}
28
+ DOC_EXTENSIONS = {'.md', '.mdx', '.qmd', '.txt', '.rst', '.html', '.yaml', '.yml'}
29
+ PAPER_EXTENSIONS = {'.pdf'}
30
+ IMAGE_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'}
31
+ OFFICE_EXTENSIONS = {'.docx', '.xlsx'}
32
+ VIDEO_EXTENSIONS = {'.mp4', '.mov', '.webm', '.mkv', '.avi', '.m4v', '.mp3', '.wav', '.m4a', '.ogg'}
33
+
34
+ CORPUS_WARN_THRESHOLD = 50_000 # words - below this, warn "you may not need a graph"
35
+ CORPUS_UPPER_THRESHOLD = 500_000 # words - above this, warn about token cost
36
+ FILE_COUNT_UPPER = 200 # files - above this, warn about token cost
37
+
38
+ # Parent directories whose contents are always sensitive.
39
+ # Checked against path.parts[:-1] (parents only) so a root-level file named
40
+ # "credentials" or "secrets" is not falsely flagged by this stage.
41
+ _SENSITIVE_DIRS = frozenset({
42
+ ".ssh", ".gnupg", ".aws", ".gcloud", "secrets", ".secrets", "credentials",
43
+ })
44
+
45
+ # Files that may contain secrets - skip silently.
46
+ # Uses lookarounds instead of \b so underscore-prefixed names like api_token.txt
47
+ # match. Both patterns use (?![a-zA-Z]) so that the trailing-underscore behavior
48
+ # is consistent: "secret_store.txt" IS flagged, "tokenizer.py" is NOT (because
49
+ # "i" after "token" is alpha and blocks the match).
50
+ # `token` is kept separate because its longer suffix "izer"/"ize" is the only
51
+ # common false-positive; other keywords have no such well-known derivatives.
52
+ _SENSITIVE_PATTERNS = [
53
+ re.compile(r'(^|[\\/])\.(env|envrc)(\.|$)', re.IGNORECASE),
54
+ re.compile(r'\.(pem|key|p12|pfx|cert|crt|der|p8)$', re.IGNORECASE),
55
+ re.compile(r'(?<![a-zA-Z0-9])(credential|secret|passwd|password|private_key)s?(?![a-zA-Z])', re.IGNORECASE),
56
+ re.compile(r'(?<![a-zA-Z0-9])tokens?(?![a-zA-Z])', re.IGNORECASE),
57
+ re.compile(r'(id_rsa|id_dsa|id_ecdsa|id_ed25519)(\.pub)?$'),
58
+ re.compile(r'(\.netrc|\.pgpass|\.htpasswd)$', re.IGNORECASE),
59
+ re.compile(r'(aws_credentials|gcloud_credentials|service.account)', re.IGNORECASE),
60
+ ]
61
+
62
+ # Signals that a .md/.txt file is actually a converted academic paper
63
+ _PAPER_SIGNALS = [
64
+ re.compile(r'\barxiv\b', re.IGNORECASE),
65
+ re.compile(r'\bdoi\s*:', re.IGNORECASE),
66
+ re.compile(r'\babstract\b', re.IGNORECASE),
67
+ re.compile(r'\bproceedings\b', re.IGNORECASE),
68
+ re.compile(r'\bjournal\b', re.IGNORECASE),
69
+ re.compile(r'\bpreprint\b', re.IGNORECASE),
70
+ re.compile(r'\\cite\{'), # LaTeX citation
71
+ re.compile(r'\[\d+\]'), # Numbered citation [1], [23] (inline)
72
+ re.compile(r'\[\n\d+\n\]'), # Numbered citation spread across lines (markdown conversion)
73
+ re.compile(r'eq\.\s*\d+|equation\s+\d+', re.IGNORECASE),
74
+ re.compile(r'\d{4}\.\d{4,5}'), # arXiv ID like 1706.03762
75
+ re.compile(r'\bwe propose\b', re.IGNORECASE), # common academic phrasing
76
+ re.compile(r'\bliterature\b', re.IGNORECASE), # "from the literature"
77
+ ]
78
+ _PAPER_SIGNAL_THRESHOLD = 3 # need at least this many signals to call it a paper
79
+
80
+
81
+ def _is_sensitive(path: Path) -> bool:
82
+ """Return True if this file likely contains secrets and should be skipped."""
83
+ # Stage 1: any PARENT directory is a known secrets dir (parts[:-1] excludes
84
+ # the filename itself so a root-level file named "credentials" is not falsely
85
+ # skipped — the name patterns in Stage 2 handle the filename).
86
+ if any(part in _SENSITIVE_DIRS for part in path.parts[:-1]):
87
+ return True
88
+ # Stage 2: filename pattern match
89
+ name = path.name
90
+ return any(p.search(name) for p in _SENSITIVE_PATTERNS)
91
+
92
+
93
+ def _looks_like_paper(path: Path) -> bool:
94
+ """Heuristic: does this text file read like an academic paper?"""
95
+ try:
96
+ # Only scan first 3000 chars for speed
97
+ text = path.read_text(encoding="utf-8", errors="ignore")[:3000]
98
+ hits = sum(1 for pattern in _PAPER_SIGNALS if pattern.search(text))
99
+ return hits >= _PAPER_SIGNAL_THRESHOLD
100
+ except Exception:
101
+ return False
102
+
103
+
104
+ _ASSET_DIR_MARKERS = {".imageset", ".xcassets", ".appiconset", ".colorset", ".launchimage"}
105
+
106
+
107
+ _SHEBANG_CODE_INTERPRETERS = {
108
+ "python", "python3", "python2",
109
+ "ruby", "perl", "node", "nodejs",
110
+ "bash", "sh", "dash", "zsh", "fish", "ksh", "tcsh",
111
+ "lua", "php", "julia", "Rscript",
112
+ }
113
+
114
+
115
+ def _shebang_file_type(path: Path) -> FileType | None:
116
+ """Peek at the first line of an extensionless file for a shebang."""
117
+ try:
118
+ with path.open("rb") as f:
119
+ first = f.read(128)
120
+ if not first.startswith(b"#!"):
121
+ return None
122
+ line = first.split(b"\n")[0].decode(errors="replace")
123
+ parts = line[2:].strip().split()
124
+ if not parts:
125
+ return None
126
+ interp = parts[0].split("/")[-1] # /usr/bin/env → env
127
+ if interp == "env" and len(parts) > 1:
128
+ interp = parts[1].split("/")[-1]
129
+ if interp in _SHEBANG_CODE_INTERPRETERS:
130
+ return FileType.CODE
131
+ except OSError:
132
+ pass
133
+ return None
134
+
135
+
136
+ def classify_file(path: Path) -> FileType | None:
137
+ # Compound extensions must be checked before simple suffix lookup
138
+ if path.name.lower().endswith(".blade.php"):
139
+ return FileType.CODE
140
+ ext = path.suffix.lower()
141
+ if not ext:
142
+ return _shebang_file_type(path)
143
+ if ext in CODE_EXTENSIONS:
144
+ return FileType.CODE
145
+ if ext in PAPER_EXTENSIONS:
146
+ # PDFs inside Xcode asset catalogs are vector icons, not papers
147
+ if any(part.endswith(tuple(_ASSET_DIR_MARKERS)) for part in path.parts):
148
+ return None
149
+ return FileType.PAPER
150
+ if ext in IMAGE_EXTENSIONS:
151
+ return FileType.IMAGE
152
+ if ext in DOC_EXTENSIONS:
153
+ # Check if it's a converted paper
154
+ if _looks_like_paper(path):
155
+ return FileType.PAPER
156
+ return FileType.DOCUMENT
157
+ if ext in OFFICE_EXTENSIONS:
158
+ return FileType.DOCUMENT
159
+ if ext in GOOGLE_WORKSPACE_EXTENSIONS:
160
+ return FileType.DOCUMENT
161
+ if ext in VIDEO_EXTENSIONS:
162
+ return FileType.VIDEO
163
+ return None
164
+
165
+
166
+ def extract_pdf_text(path: Path) -> str:
167
+ """Extract plain text from a PDF file using pypdf."""
168
+ try:
169
+ from pypdf import PdfReader
170
+ reader = PdfReader(str(path))
171
+ pages = []
172
+ for page in reader.pages:
173
+ text = page.extract_text()
174
+ if text:
175
+ pages.append(text)
176
+ return "\n".join(pages)
177
+ except Exception:
178
+ return ""
179
+
180
+
181
+ def docx_to_markdown(path: Path) -> str:
182
+ """Convert a .docx file to markdown text using python-docx."""
183
+ try:
184
+ from docx import Document
185
+ from docx.oxml.ns import qn
186
+ doc = Document(str(path))
187
+ lines = []
188
+ for para in doc.paragraphs:
189
+ style = para.style.name if para.style else ""
190
+ text = para.text.strip()
191
+ if not text:
192
+ lines.append("")
193
+ continue
194
+ if style.startswith("Heading 1"):
195
+ lines.append(f"# {text}")
196
+ elif style.startswith("Heading 2"):
197
+ lines.append(f"## {text}")
198
+ elif style.startswith("Heading 3"):
199
+ lines.append(f"### {text}")
200
+ elif style.startswith("List"):
201
+ lines.append(f"- {text}")
202
+ else:
203
+ lines.append(text)
204
+ # Tables
205
+ for table in doc.tables:
206
+ rows = [[cell.text.strip() for cell in row.cells] for row in table.rows]
207
+ if not rows:
208
+ continue
209
+ header = "| " + " | ".join(rows[0]) + " |"
210
+ sep = "| " + " | ".join("---" for _ in rows[0]) + " |"
211
+ lines.extend([header, sep])
212
+ for row in rows[1:]:
213
+ lines.append("| " + " | ".join(row) + " |")
214
+ return "\n".join(lines)
215
+ except ImportError:
216
+ return ""
217
+ except Exception:
218
+ return ""
219
+
220
+
221
+ def xlsx_to_markdown(path: Path) -> str:
222
+ """Convert an .xlsx file to markdown text using openpyxl."""
223
+ try:
224
+ import openpyxl
225
+ wb = openpyxl.load_workbook(str(path), read_only=True, data_only=True)
226
+ sections = []
227
+ for sheet_name in wb.sheetnames:
228
+ ws = wb[sheet_name]
229
+ rows = []
230
+ for row in ws.iter_rows(values_only=True):
231
+ if all(cell is None for cell in row):
232
+ continue
233
+ rows.append([str(cell) if cell is not None else "" for cell in row])
234
+ if not rows:
235
+ continue
236
+ sections.append(f"## Sheet: {sheet_name}")
237
+ if len(rows) >= 1:
238
+ header = "| " + " | ".join(rows[0]) + " |"
239
+ sep = "| " + " | ".join("---" for _ in rows[0]) + " |"
240
+ sections.extend([header, sep])
241
+ for row in rows[1:]:
242
+ sections.append("| " + " | ".join(row) + " |")
243
+ wb.close()
244
+ return "\n".join(sections)
245
+ except ImportError:
246
+ return ""
247
+ except Exception:
248
+ return ""
249
+
250
+
251
+ def xlsx_extract_structure(path: Path) -> dict:
252
+ """Extract structural nodes (sheets, named tables, column headers) from an .xlsx file.
253
+
254
+ Returns a nodes/edges dict compatible with the graphify extract pipeline.
255
+ Used in addition to xlsx_to_markdown so Claude sees both structure and content.
256
+ """
257
+ def _nid(*parts: str) -> str:
258
+ return re.sub(r"[^a-z0-9_]", "_", "_".join(p.lower() for p in parts).strip("_"))
259
+
260
+ try:
261
+ import openpyxl
262
+ except ImportError:
263
+ return {"nodes": [], "edges": []}
264
+
265
+ try:
266
+ wb = openpyxl.load_workbook(str(path), read_only=False, data_only=True)
267
+ except Exception:
268
+ return {"nodes": [], "edges": []}
269
+
270
+ # F-035: typo fix — was `_re.sub` (NameError, but unreachable because the
271
+ # whole xlsx codepath is currently behind a feature flag / not yet wired
272
+ # into the dispatcher). Before re-enabling this path, re-audit it for
273
+ # zip/XML bombs (openpyxl is built on top of zipfile and lxml-style XML
274
+ # parsing — a malicious .xlsx can blow up memory at load_workbook time).
275
+ stem = re.sub(r"[^a-z0-9]", "_", path.stem.lower())
276
+ str_path = str(path)
277
+ file_nid = _nid(str_path)
278
+ nodes: list[dict] = [{"id": file_nid, "label": path.name, "file_type": "document",
279
+ "source_file": str_path, "source_location": None}]
280
+ edges: list[dict] = []
281
+ seen: set[str] = {file_nid}
282
+
283
+ def _add(nid: str, label: str) -> None:
284
+ if nid not in seen:
285
+ seen.add(nid)
286
+ nodes.append({"id": nid, "label": label, "file_type": "document",
287
+ "source_file": str_path, "source_location": None})
288
+
289
+ def _edge(src: str, tgt: str, relation: str) -> None:
290
+ edges.append({"source": src, "target": tgt, "relation": relation,
291
+ "confidence": "EXTRACTED", "source_file": str_path,
292
+ "source_location": None, "weight": 1.0})
293
+
294
+ for sheet_name in wb.sheetnames:
295
+ ws = wb[sheet_name]
296
+ sheet_nid = _nid(stem, sheet_name)
297
+ _add(sheet_nid, f"{sheet_name} (sheet)")
298
+ _edge(file_nid, sheet_nid, "contains")
299
+
300
+ # Named Excel Tables (ListObjects)
301
+ if hasattr(ws, "tables"):
302
+ for tbl in ws.tables.values():
303
+ tbl_nid = _nid(stem, sheet_name, tbl.name)
304
+ _add(tbl_nid, tbl.name)
305
+ _edge(sheet_nid, tbl_nid, "contains")
306
+ # Column headers from table header row
307
+ ref = tbl.ref # e.g. "A1:D10"
308
+ if ref:
309
+ try:
310
+ from openpyxl.utils import range_boundaries
311
+ min_col, min_row, max_col, _ = range_boundaries(ref)
312
+ header_row = list(ws.iter_rows(min_row=min_row, max_row=min_row,
313
+ min_col=min_col, max_col=max_col,
314
+ values_only=True))
315
+ if header_row:
316
+ for col_name in header_row[0]:
317
+ if col_name:
318
+ col_nid = _nid(stem, tbl.name, str(col_name))
319
+ _add(col_nid, str(col_name))
320
+ _edge(tbl_nid, col_nid, "contains")
321
+ except Exception:
322
+ pass
323
+ else:
324
+ # Fallback: first non-empty row as column headers
325
+ for row in ws.iter_rows(max_row=1, values_only=True):
326
+ for cell in row:
327
+ if cell:
328
+ col_nid = _nid(stem, sheet_name, str(cell))
329
+ _add(col_nid, str(cell))
330
+ _edge(sheet_nid, col_nid, "contains")
331
+ break
332
+
333
+ try:
334
+ wb.close()
335
+ except Exception:
336
+ pass
337
+
338
+ return {"nodes": nodes, "edges": edges}
339
+
340
+
341
+ def convert_office_file(path: Path, out_dir: Path) -> Path | None:
342
+ """Convert a .docx or .xlsx to a markdown sidecar in out_dir.
343
+
344
+ Returns the path of the converted .md file, or None if conversion failed
345
+ or the required library is not installed.
346
+ """
347
+ ext = path.suffix.lower()
348
+ if ext == ".docx":
349
+ text = docx_to_markdown(path)
350
+ elif ext == ".xlsx":
351
+ text = xlsx_to_markdown(path)
352
+ else:
353
+ return None
354
+
355
+ if not text.strip():
356
+ return None
357
+
358
+ out_dir.mkdir(parents=True, exist_ok=True)
359
+ # Use a stable name derived from the original path to avoid collisions
360
+ import hashlib
361
+ name_hash = hashlib.sha256(str(path.resolve()).encode()).hexdigest()[:8]
362
+ out_path = out_dir / f"{path.stem}_{name_hash}.md"
363
+ out_path.write_text(
364
+ f"<!-- converted from {path.name} -->\n\n{text}",
365
+ encoding="utf-8",
366
+ )
367
+ return out_path
368
+
369
+
370
+ def count_words(path: Path) -> int:
371
+ try:
372
+ ext = path.suffix.lower()
373
+ if ext == ".pdf":
374
+ return len(extract_pdf_text(path).split())
375
+ if ext == ".docx":
376
+ return len(docx_to_markdown(path).split())
377
+ if ext == ".xlsx":
378
+ return len(xlsx_to_markdown(path).split())
379
+ return len(path.read_text(encoding="utf-8", errors="ignore").split())
380
+ except Exception:
381
+ return 0
382
+
383
+
384
+ # Directory names to always skip - venvs, caches, build artifacts, deps
385
+ _SKIP_DIRS = {
386
+ "venv", ".venv", "env", ".env",
387
+ "node_modules", "__pycache__", ".git",
388
+ "dist", "build", "target", "out",
389
+ "site-packages", "lib64",
390
+ ".pytest_cache", ".mypy_cache", ".ruff_cache",
391
+ ".tox", ".eggs", "*.egg-info",
392
+ "graphify-out", # never treat own output as source input (#524)
393
+ # Coverage/test-artefact dirs — generated, never architecturally meaningful
394
+ "coverage", "lcov-report", # Vitest/Istanbul/nyc HTML reports (#870)
395
+ "visual-tests", "visual-test", # Playwright/visual-regression bundles (#869)
396
+ "__snapshots__", "snapshots", # Jest/Vitest snapshot dirs
397
+ "storybook-static", # Storybook production build output
398
+ "dist-protected", # Protected dist variants (same noise as dist)
399
+ # Framework cache/build dirs — generated, never architecturally meaningful (#873)
400
+ ".next", ".nuxt", ".turbo", ".angular",
401
+ ".idea", ".cache", ".parcel-cache", ".svelte-kit", ".terraform", ".serverless",
402
+ ".graphify", # graphify's own extraction cache — never index self-generated data
403
+ }
404
+
405
+ # Large generated files that are never useful to extract
406
+ _SKIP_FILES = {
407
+ "package-lock.json", "yarn.lock", "pnpm-lock.yaml",
408
+ "Cargo.lock", "poetry.lock", "Gemfile.lock",
409
+ "composer.lock", "go.sum", "go.work.sum",
410
+ }
411
+
412
+ def _is_noise_dir(part: str) -> bool:
413
+ """Return True if this directory name looks like a venv, cache, or dep dir."""
414
+ if part in _SKIP_DIRS:
415
+ return True
416
+ # Catch *_venv, *_repo/site-packages patterns
417
+ if part.endswith("_venv") or part.endswith("_env"):
418
+ return True
419
+ if part.endswith(".egg-info"):
420
+ return True
421
+ return False
422
+
423
+
424
+ _VCS_MARKERS = (".git", ".hg", ".svn", "_darcs", ".fossil")
425
+
426
+
427
+ def _parse_gitignore_line(raw: str) -> str:
428
+ """Parse one raw line from a .graphifyignore file per gitignore spec.
429
+
430
+ - Strip newline chars
431
+ - Strip inline comments (whitespace + # suffix), but only when # is
432
+ preceded by whitespace — so path#with#hash.py is preserved
433
+ - Unescape \\# to literal #
434
+ - Remove trailing spaces unless escaped with backslash
435
+ - Strip leading whitespace
436
+ - Return empty string for blank lines and full-line comments
437
+ """
438
+ line = raw.rstrip("\n\r")
439
+ line = line.lstrip()
440
+ if not line or line.startswith("#"):
441
+ return ""
442
+ # Strip inline comments: require whitespace before # (gitignore extension)
443
+ line = re.sub(r"\s+#+[^\\].*$", "", line)
444
+ # Unescape \# → literal #
445
+ line = line.replace("\\#", "#")
446
+ # Remove unescaped trailing spaces (per gitignore spec)
447
+ line = re.sub(r"(?<!\\) +$", "", line)
448
+ return line
449
+
450
+
451
+ def _find_vcs_root(start: Path) -> Path | None:
452
+ """Walk upward from start; return the first directory containing a VCS marker."""
453
+ current = start.resolve()
454
+ home = Path.home()
455
+ while True:
456
+ if any((current / m).exists() for m in _VCS_MARKERS):
457
+ return current
458
+ parent = current.parent
459
+ if parent == current or current == home:
460
+ return None
461
+ current = parent
462
+
463
+
464
+ def _load_graphifyignore(root: Path) -> list[tuple[Path, str]]:
465
+ """Read .graphifyignore files and return (anchor_dir, pattern) pairs.
466
+
467
+ Patterns are returned outer-first so that inner (closer) rules are
468
+ appended last and win via last-match-wins semantics — matching gitignore
469
+ behavior exactly.
470
+
471
+ Walk ceiling: the nearest VCS root if inside a repo, otherwise the scan
472
+ root itself (hermetic — no leakage across unrelated sibling projects).
473
+ """
474
+ root = root.resolve()
475
+ ceiling = _find_vcs_root(root) or root
476
+
477
+ # Collect ancestor dirs from ceiling down to root (outer → inner)
478
+ dirs: list[Path] = []
479
+ current = root
480
+ while True:
481
+ dirs.append(current)
482
+ if current == ceiling:
483
+ break
484
+ current = current.parent
485
+ dirs.reverse() # ceiling first, scan root last
486
+
487
+ patterns: list[tuple[Path, str]] = []
488
+ for d in dirs:
489
+ ignore_file = d / ".graphifyignore"
490
+ if ignore_file.exists():
491
+ for raw in ignore_file.read_text(encoding="utf-8", errors="ignore").splitlines():
492
+ line = _parse_gitignore_line(raw)
493
+ if line:
494
+ patterns.append((d, line))
495
+ return patterns
496
+
497
+
498
+ def _is_ignored(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
499
+ """Return True if the path should be ignored per .graphifyignore patterns.
500
+
501
+ Uses gitignore last-match-wins semantics: all patterns are evaluated in
502
+ order; the final matching pattern determines the result. Negation patterns
503
+ (starting with !) un-ignore a previously ignored path.
504
+
505
+ Enforces gitignore's parent-exclusion rule: a ! pattern cannot re-include
506
+ a file whose ancestor directory is already excluded.
507
+ """
508
+ if not patterns:
509
+ return False
510
+
511
+ def _eval(target: Path) -> bool:
512
+ """Apply last-match-wins to a single target path."""
513
+ def _matches(rel: str, p: str) -> bool:
514
+ parts = rel.split("/")
515
+ if fnmatch.fnmatch(rel, p):
516
+ return True
517
+ if fnmatch.fnmatch(target.name, p):
518
+ return True
519
+ for i, part in enumerate(parts):
520
+ if fnmatch.fnmatch(part, p):
521
+ return True
522
+ if fnmatch.fnmatch("/".join(parts[:i + 1]), p):
523
+ return True
524
+ return False
525
+
526
+ result = False
527
+ for anchor, pattern in patterns:
528
+ negated = pattern.startswith("!")
529
+ raw = pattern[1:] if negated else pattern
530
+ anchored = raw.startswith("/")
531
+ p = raw.strip("/")
532
+ if not p:
533
+ continue
534
+
535
+ matched = False
536
+ if anchored:
537
+ try:
538
+ rel_anchor = str(target.relative_to(anchor)).replace(os.sep, "/")
539
+ matched = _matches(rel_anchor, p)
540
+ except ValueError:
541
+ pass
542
+ else:
543
+ try:
544
+ rel = str(target.relative_to(root)).replace(os.sep, "/")
545
+ matched = _matches(rel, p)
546
+ except ValueError:
547
+ pass
548
+ if not matched and anchor != root:
549
+ try:
550
+ rel_anchor = str(target.relative_to(anchor)).replace(os.sep, "/")
551
+ matched = _matches(rel_anchor, p)
552
+ except ValueError:
553
+ pass
554
+
555
+ if matched:
556
+ result = not negated # last match wins; ! flips to un-ignore
557
+ return result
558
+
559
+ # Gitignore parent-exclusion rule: a ! re-include cannot rescue a file
560
+ # whose ancestor directory is already excluded. Walk ancestors top-down;
561
+ # if any ancestor is excluded, the file is excluded regardless of later
562
+ # ! patterns targeting the file or a sub-path.
563
+ try:
564
+ rel_parts = path.relative_to(root).parts
565
+ except ValueError:
566
+ return _eval(path)
567
+
568
+ ancestor = root
569
+ for part in rel_parts[:-1]:
570
+ ancestor = ancestor / part
571
+ if _eval(ancestor):
572
+ return True
573
+ return _eval(path)
574
+
575
+
576
+ def _load_graphifyinclude(root: Path) -> list[tuple[Path, str]]:
577
+ """Read .graphifyinclude allowlist patterns from root and ancestors.
578
+
579
+ Include patterns opt matching hidden files/dirs into traversal. Sensitive
580
+ files and hard-skipped noise directories are still excluded later.
581
+ Uses the same VCS-root ceiling logic as _load_graphifyignore.
582
+ """
583
+ root = root.resolve()
584
+ ceiling = _find_vcs_root(root) or root
585
+
586
+ dirs: list[Path] = []
587
+ current = root
588
+ while True:
589
+ dirs.append(current)
590
+ if current == ceiling:
591
+ break
592
+ current = current.parent
593
+ dirs.reverse()
594
+
595
+ patterns: list[tuple[Path, str]] = []
596
+ for d in dirs:
597
+ include_file = d / ".graphifyinclude"
598
+ if include_file.exists():
599
+ for raw in include_file.read_text(encoding="utf-8", errors="ignore").splitlines():
600
+ line = _parse_gitignore_line(raw)
601
+ if line:
602
+ patterns.append((d, line))
603
+ return patterns
604
+
605
+
606
+ def _is_included(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
607
+ """Return True if path matches any .graphifyinclude allowlist pattern."""
608
+ if not patterns:
609
+ return False
610
+
611
+ def _matches(rel: str, p: str) -> bool:
612
+ parts = rel.split("/")
613
+ if fnmatch.fnmatch(rel, p):
614
+ return True
615
+ if fnmatch.fnmatch(path.name, p):
616
+ return True
617
+ for i, part in enumerate(parts):
618
+ if fnmatch.fnmatch(part, p):
619
+ return True
620
+ if fnmatch.fnmatch("/".join(parts[:i + 1]), p):
621
+ return True
622
+ return False
623
+
624
+ for anchor, pattern in patterns:
625
+ anchored = pattern.startswith("/")
626
+ p = pattern.strip("/")
627
+ if not p:
628
+ continue
629
+ if anchored:
630
+ try:
631
+ rel_anchor = str(path.relative_to(anchor)).replace(os.sep, "/")
632
+ if _matches(rel_anchor, p):
633
+ return True
634
+ except ValueError:
635
+ pass
636
+ else:
637
+ try:
638
+ rel = str(path.relative_to(root)).replace(os.sep, "/")
639
+ if _matches(rel, p):
640
+ return True
641
+ except ValueError:
642
+ pass
643
+ if anchor != root:
644
+ try:
645
+ rel_anchor = str(path.relative_to(anchor)).replace(os.sep, "/")
646
+ if _matches(rel_anchor, p):
647
+ return True
648
+ except ValueError:
649
+ pass
650
+ return False
651
+
652
+
653
+ def _could_contain_included_path(path: Path, root: Path, patterns: list[tuple[Path, str]]) -> bool:
654
+ """Return True if a directory may contain files matched by .graphifyinclude."""
655
+ if not patterns:
656
+ return False
657
+
658
+ rels: list[str] = []
659
+ try:
660
+ rels.append(str(path.relative_to(root)).replace(os.sep, "/"))
661
+ except ValueError:
662
+ pass
663
+ for anchor, _ in patterns:
664
+ if anchor != root:
665
+ try:
666
+ rels.append(str(path.relative_to(anchor)).replace(os.sep, "/"))
667
+ except ValueError:
668
+ pass
669
+
670
+ for rel in rels:
671
+ rel = rel.strip("/")
672
+ if not rel:
673
+ return True
674
+ for _, pattern in patterns:
675
+ p = pattern.strip("/")
676
+ if not p:
677
+ continue
678
+ if p == rel or p.startswith(rel + "/"):
679
+ return True
680
+ if fnmatch.fnmatch(rel, p):
681
+ return True
682
+ return False
683
+
684
+
685
+ def _auto_follow_symlinks(root: Path) -> bool:
686
+ """Auto-detect: ``True`` if ``root`` has any direct symlinked child.
687
+
688
+ Allows "fake working dir" patterns (e.g. a folder full of symlinks pointing
689
+ at scattered source dirs across the user's machine) to work transparently
690
+ without the caller having to know to pass ``follow_symlinks=True``.
691
+
692
+ Override is always possible by passing an explicit ``follow_symlinks=True``
693
+ or ``follow_symlinks=False`` to :func:`detect` / :func:`detect_incremental`.
694
+ """
695
+ try:
696
+ for p in root.iterdir():
697
+ if p.is_symlink():
698
+ return True
699
+ except (OSError, PermissionError):
700
+ pass
701
+ return False
702
+
703
+
704
+ def detect(root: Path, *, follow_symlinks: bool | None = None, google_workspace: bool | None = None) -> dict:
705
+ root = root.resolve()
706
+ if follow_symlinks is None:
707
+ follow_symlinks = _auto_follow_symlinks(root)
708
+ google_workspace = google_workspace_enabled() if google_workspace is None else google_workspace
709
+ files: dict[FileType, list[str]] = {
710
+ FileType.CODE: [],
711
+ FileType.DOCUMENT: [],
712
+ FileType.PAPER: [],
713
+ FileType.IMAGE: [],
714
+ FileType.VIDEO: [],
715
+ }
716
+ total_words = 0
717
+
718
+ skipped_sensitive: list[str] = []
719
+ ignore_patterns = _load_graphifyignore(root)
720
+ include_patterns = _load_graphifyinclude(root)
721
+
722
+ # Always include graphify-out/memory/ - query results filed back into the graph
723
+ memory_dir = root / "graphify-out" / "memory"
724
+ scan_paths = [root]
725
+ if memory_dir.exists():
726
+ scan_paths.append(memory_dir)
727
+
728
+ seen: set[Path] = set()
729
+ all_files: list[Path] = []
730
+
731
+ for scan_root in scan_paths:
732
+ in_memory_tree = memory_dir.exists() and str(scan_root).startswith(str(memory_dir))
733
+ for dirpath, dirnames, filenames in os.walk(scan_root, followlinks=follow_symlinks):
734
+ dp = Path(dirpath)
735
+ if follow_symlinks and os.path.islink(dirpath):
736
+ real = os.path.realpath(dirpath)
737
+ parent_real = os.path.realpath(os.path.dirname(dirpath))
738
+ if parent_real == real or parent_real.startswith(real + os.sep):
739
+ dirnames.clear()
740
+ continue
741
+ if not in_memory_tree:
742
+ # Prune noise dirs in-place so os.walk never descends into them.
743
+ # Dot dirs are allowed — users often want .github/, .claude/, etc.
744
+ # Framework caches (.next, .nuxt, …) are caught by _is_noise_dir.
745
+ # When negation patterns (!) exist, skip directory-level ignore
746
+ # pruning so negated files inside can still be reached.
747
+ has_negation = any(p.startswith("!") for _, p in ignore_patterns)
748
+ dirnames[:] = [
749
+ d for d in dirnames
750
+ if not _is_noise_dir(d)
751
+ and (has_negation or not _is_ignored(dp / d, root, ignore_patterns))
752
+ ]
753
+ for fname in filenames:
754
+ if fname in _SKIP_FILES:
755
+ continue
756
+ p = dp / fname
757
+ if p not in seen:
758
+ seen.add(p)
759
+ all_files.append(p)
760
+
761
+ converted_dir = root / "graphify-out" / "converted"
762
+
763
+ for p in all_files:
764
+ # For memory dir files, skip hidden/noise filtering
765
+ in_memory = memory_dir.exists() and str(p).startswith(str(memory_dir))
766
+ if not in_memory:
767
+ # Skip files inside our own converted/ dir (avoid re-processing sidecars)
768
+ if str(p).startswith(str(converted_dir)):
769
+ continue
770
+ if _is_ignored(p, root, ignore_patterns):
771
+ continue
772
+ if _is_sensitive(p):
773
+ skipped_sensitive.append(str(p))
774
+ continue
775
+ ftype = classify_file(p)
776
+ if ftype:
777
+ if p.suffix.lower() in GOOGLE_WORKSPACE_EXTENSIONS:
778
+ if not google_workspace:
779
+ skipped_sensitive.append(
780
+ str(p)
781
+ + " [Google Workspace shortcut skipped - pass --google-workspace "
782
+ "or set GRAPHIFY_GOOGLE_WORKSPACE=1]"
783
+ )
784
+ continue
785
+ try:
786
+ md_path = convert_google_workspace_file(p, converted_dir, xlsx_to_markdown=xlsx_to_markdown)
787
+ except Exception as exc:
788
+ skipped_sensitive.append(str(p) + f" [Google Workspace export failed: {exc}]")
789
+ continue
790
+ if md_path:
791
+ if _is_ignored(md_path, root, ignore_patterns):
792
+ continue
793
+ files[ftype].append(str(md_path))
794
+ total_words += count_words(md_path)
795
+ else:
796
+ skipped_sensitive.append(str(p) + " [Google Workspace export produced no readable text]")
797
+ continue
798
+ # Office files: convert to markdown sidecar so subagents can read them
799
+ if p.suffix.lower() in OFFICE_EXTENSIONS:
800
+ md_path = convert_office_file(p, converted_dir)
801
+ if md_path:
802
+ if _is_ignored(md_path, root, ignore_patterns):
803
+ continue
804
+ files[ftype].append(str(md_path))
805
+ total_words += count_words(md_path)
806
+ else:
807
+ # Conversion failed (library not installed) - skip with note
808
+ skipped_sensitive.append(str(p) + " [office conversion failed - pip install graphifyy[office]]")
809
+ continue
810
+ files[ftype].append(str(p))
811
+ if ftype != FileType.VIDEO:
812
+ total_words += count_words(p)
813
+
814
+ total_files = sum(len(v) for v in files.values())
815
+ needs_graph = total_words >= CORPUS_WARN_THRESHOLD
816
+
817
+ # Determine warning - lower bound, upper bound, or sensitive files skipped
818
+ warning: str | None = None
819
+ if not needs_graph:
820
+ warning = (
821
+ f"Corpus is ~{total_words:,} words - fits in a single context window. "
822
+ f"You may not need a graph."
823
+ )
824
+ elif total_words >= CORPUS_UPPER_THRESHOLD or total_files >= FILE_COUNT_UPPER:
825
+ warning = (
826
+ f"Large corpus: {total_files} files · ~{total_words:,} words. "
827
+ f"Semantic extraction will be expensive (many Claude tokens). "
828
+ f"Consider running on a subfolder, or use --no-semantic to run AST-only."
829
+ )
830
+
831
+ return {
832
+ "files": {k.value: v for k, v in files.items()},
833
+ "total_files": total_files,
834
+ "total_words": total_words,
835
+ "needs_graph": needs_graph,
836
+ "warning": warning,
837
+ "skipped_sensitive": skipped_sensitive,
838
+ "graphifyignore_patterns": len(ignore_patterns),
839
+ }
840
+
841
+
842
+ def _md5_file(path: Path) -> str:
843
+ """MD5 of file contents streamed in 64KB chunks — for change detection only."""
844
+ import hashlib as _hl
845
+ h = _hl.md5(usedforsecurity=False)
846
+ try:
847
+ with path.open("rb") as f:
848
+ for chunk in iter(lambda: f.read(65536), b""):
849
+ h.update(chunk)
850
+ except OSError:
851
+ return ""
852
+ return h.hexdigest()
853
+
854
+
855
+ def load_manifest(manifest_path: str = _MANIFEST_PATH) -> dict:
856
+ """Load the manifest from a previous run. Returns {} on any error."""
857
+ try:
858
+ return json.loads(Path(manifest_path).read_text(encoding="utf-8"))
859
+ except Exception:
860
+ return {}
861
+
862
+
863
+ def save_manifest(
864
+ files: dict[str, list[str]],
865
+ manifest_path: str = _MANIFEST_PATH,
866
+ *,
867
+ kind: str = "both",
868
+ ) -> None:
869
+ """Save current file mtimes + content hashes for change detection.
870
+
871
+ kind="ast" — written by `graphify update` (AST-only rebuild). Stamps
872
+ ast_hash; preserves an existing semantic_hash only when
873
+ the file content is unchanged (mtime + hash match).
874
+ kind="semantic" — written by `graphify extract` after semantic extraction.
875
+ Stamps semantic_hash; preserves existing ast_hash.
876
+ kind="both" — full pipeline: stamps both hashes (default).
877
+ """
878
+ existing = load_manifest(manifest_path)
879
+
880
+ def _normalise_entry(entry):
881
+ if isinstance(entry, (int, float)):
882
+ return {"mtime": entry, "ast_hash": "", "semantic_hash": ""}
883
+ if isinstance(entry, dict) and "hash" in entry and "ast_hash" not in entry:
884
+ return {"mtime": entry.get("mtime", 0), "ast_hash": entry["hash"], "semantic_hash": ""}
885
+ if isinstance(entry, dict):
886
+ return entry
887
+ return None
888
+
889
+ # Seed from the existing manifest so incremental callers passing a subset
890
+ # of files don't silently erase entries for untouched files (#917).
891
+ # Prune entries whose file no longer exists on disk — those are genuine
892
+ # deletions that detect_incremental() should treat as gone.
893
+ manifest: dict[str, dict] = {}
894
+ for f, entry in existing.items():
895
+ normalised = _normalise_entry(entry)
896
+ if normalised is None:
897
+ continue
898
+ try:
899
+ if Path(f).exists():
900
+ manifest[f] = normalised
901
+ except OSError:
902
+ continue
903
+
904
+ for file_list in files.values():
905
+ for f in file_list:
906
+ try:
907
+ p = Path(f)
908
+ mtime = p.stat().st_mtime
909
+ h = _md5_file(p)
910
+ except OSError:
911
+ continue # file deleted between detect() and manifest write
912
+ prev = _normalise_entry(existing.get(f, {})) or {}
913
+ entry: dict = {"mtime": mtime}
914
+ if kind in ("ast", "both"):
915
+ entry["ast_hash"] = h
916
+ else:
917
+ entry["ast_hash"] = prev.get("ast_hash", "")
918
+ if kind in ("semantic", "both"):
919
+ entry["semantic_hash"] = h
920
+ else:
921
+ # Preserve semantic_hash only when content is unchanged
922
+ entry["semantic_hash"] = prev.get("semantic_hash", "") if h == prev.get("ast_hash", "") else ""
923
+ manifest[f] = entry
924
+ Path(manifest_path).parent.mkdir(parents=True, exist_ok=True)
925
+ Path(manifest_path).write_text(json.dumps(manifest, indent=2), encoding="utf-8")
926
+
927
+
928
+ def detect_incremental(
929
+ root: Path,
930
+ manifest_path: str = _MANIFEST_PATH,
931
+ *,
932
+ follow_symlinks: bool | None = None,
933
+ google_workspace: bool | None = None,
934
+ kind: str = "semantic",
935
+ ) -> dict:
936
+ """Like detect(), but returns only new or modified files since the last run.
937
+
938
+ kind="semantic" (default for extract): a file is "changed" when its
939
+ semantic_hash is missing or its content has changed since the last
940
+ semantic extraction pass. Use this for `graphify extract` so that
941
+ files touched by `graphify update` (AST-only) are re-extracted
942
+ semantically.
943
+ kind="ast": a file is "changed" when its ast_hash is missing or its
944
+ content has changed. Use this for `graphify update`.
945
+
946
+ Fast path: mtime unchanged + hash matches → unchanged (free, no disk IO
947
+ beyond stat). Slow path: mtime bumped → compare MD5 against the relevant
948
+ hash field before re-extracting.
949
+
950
+ Backwards compatible with legacy manifests storing plain float mtime values
951
+ or {mtime, hash} dicts (treated as ast_hash only; semantic_hash = miss).
952
+
953
+ The ``follow_symlinks`` flag is forwarded to :func:`detect` so corpora that
954
+ rely on symlinked sub-trees (e.g. a ``state_of_truth/`` symlink pointing to a
955
+ directory outside the scan root) are scanned consistently between full and
956
+ incremental runs. ``None`` (default) means auto-detect: ``True`` when ``root``
957
+ contains at least one direct symlinked child, ``False`` otherwise.
958
+ """
959
+ full = detect(root, follow_symlinks=follow_symlinks, google_workspace=google_workspace)
960
+ manifest = load_manifest(manifest_path)
961
+
962
+ if not manifest:
963
+ # No previous run - treat everything as new
964
+ full["incremental"] = True
965
+ full["new_files"] = full["files"]
966
+ full["unchanged_files"] = {k: [] for k in full["files"]}
967
+ full["new_total"] = full["total_files"]
968
+ return full
969
+
970
+ new_files: dict[str, list[str]] = {k: [] for k in full["files"]}
971
+ unchanged_files: dict[str, list[str]] = {k: [] for k in full["files"]}
972
+
973
+ for ftype, file_list in full["files"].items():
974
+ for f in file_list:
975
+ stored = manifest.get(f)
976
+ try:
977
+ current_mtime = Path(f).stat().st_mtime
978
+ except Exception:
979
+ current_mtime = 0
980
+
981
+ # Legacy manifest: plain float value — treat as ast_hash only
982
+ if isinstance(stored, (int, float)):
983
+ changed = stored is None or current_mtime > stored
984
+ elif isinstance(stored, dict):
985
+ # Normalise legacy {mtime, hash} to new schema
986
+ if "hash" in stored and "ast_hash" not in stored:
987
+ stored = {"mtime": stored.get("mtime", 0), "ast_hash": stored["hash"], "semantic_hash": ""}
988
+ hash_key = "semantic_hash" if kind == "semantic" else "ast_hash"
989
+ stored_hash = stored.get(hash_key, "")
990
+ # Missing semantic_hash means update ran but extract hasn't — always re-extract
991
+ if not stored_hash:
992
+ changed = True
993
+ else:
994
+ stored_mtime = stored.get("mtime")
995
+ if stored_mtime is None or current_mtime != stored_mtime:
996
+ # mtime bumped — verify with content hash before re-extracting
997
+ changed = _md5_file(Path(f)) != stored_hash
998
+ else:
999
+ changed = False
1000
+ else:
1001
+ changed = True # unknown format, re-extract to be safe
1002
+
1003
+ if changed:
1004
+ new_files[ftype].append(f)
1005
+ else:
1006
+ unchanged_files[ftype].append(f)
1007
+
1008
+ # Files in manifest that no longer exist - their cached nodes are now ghost nodes
1009
+ current_files = {f for flist in full["files"].values() for f in flist}
1010
+ deleted_files = [f for f in manifest if f not in current_files]
1011
+
1012
+ new_total = sum(len(v) for v in new_files.values())
1013
+ full["incremental"] = True
1014
+ full["new_files"] = new_files
1015
+ full["unchanged_files"] = unchanged_files
1016
+ full["new_total"] = new_total
1017
+ full["deleted_files"] = deleted_files
1018
+ return full