graphify-sfdx 0.1.0__tar.gz

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 (289) hide show
  1. graphify_sfdx-0.1.0/LICENSE +22 -0
  2. graphify_sfdx-0.1.0/NOTICE +8 -0
  3. graphify_sfdx-0.1.0/PKG-INFO +345 -0
  4. graphify_sfdx-0.1.0/README.md +207 -0
  5. graphify_sfdx-0.1.0/graphify/__init__.py +28 -0
  6. graphify_sfdx-0.1.0/graphify/__main__.py +4717 -0
  7. graphify_sfdx-0.1.0/graphify/_minhash.py +107 -0
  8. graphify_sfdx-0.1.0/graphify/affected.py +177 -0
  9. graphify_sfdx-0.1.0/graphify/always_on/agents-md.md +12 -0
  10. graphify_sfdx-0.1.0/graphify/always_on/antigravity-rules.md +14 -0
  11. graphify_sfdx-0.1.0/graphify/always_on/claude-md.md +9 -0
  12. graphify_sfdx-0.1.0/graphify/always_on/gemini-md.md +9 -0
  13. graphify_sfdx-0.1.0/graphify/always_on/kiro-steering.md +5 -0
  14. graphify_sfdx-0.1.0/graphify/always_on/vscode-instructions.md +17 -0
  15. graphify_sfdx-0.1.0/graphify/analyze.py +732 -0
  16. graphify_sfdx-0.1.0/graphify/benchmark.py +155 -0
  17. graphify_sfdx-0.1.0/graphify/build.py +555 -0
  18. graphify_sfdx-0.1.0/graphify/cache.py +475 -0
  19. graphify_sfdx-0.1.0/graphify/callflow_html.py +2020 -0
  20. graphify_sfdx-0.1.0/graphify/cargo_introspect.py +98 -0
  21. graphify_sfdx-0.1.0/graphify/cluster.py +272 -0
  22. graphify_sfdx-0.1.0/graphify/command-kilo.md +15 -0
  23. graphify_sfdx-0.1.0/graphify/dedup.py +474 -0
  24. graphify_sfdx-0.1.0/graphify/detect.py +1425 -0
  25. graphify_sfdx-0.1.0/graphify/diagnostics.py +390 -0
  26. graphify_sfdx-0.1.0/graphify/export.py +1516 -0
  27. graphify_sfdx-0.1.0/graphify/extract.py +12396 -0
  28. graphify_sfdx-0.1.0/graphify/global_graph.py +182 -0
  29. graphify_sfdx-0.1.0/graphify/google_workspace.py +223 -0
  30. graphify_sfdx-0.1.0/graphify/hooks.py +457 -0
  31. graphify_sfdx-0.1.0/graphify/ingest.py +331 -0
  32. graphify_sfdx-0.1.0/graphify/llm.py +2167 -0
  33. graphify_sfdx-0.1.0/graphify/manifest.py +4 -0
  34. graphify_sfdx-0.1.0/graphify/mcp_ingest.py +392 -0
  35. graphify_sfdx-0.1.0/graphify/multigraph_compat.py +212 -0
  36. graphify_sfdx-0.1.0/graphify/pg_introspect.py +142 -0
  37. graphify_sfdx-0.1.0/graphify/prs.py +751 -0
  38. graphify_sfdx-0.1.0/graphify/querylog.py +70 -0
  39. graphify_sfdx-0.1.0/graphify/report.py +218 -0
  40. graphify_sfdx-0.1.0/graphify/salesforce/__init__.py +282 -0
  41. graphify_sfdx-0.1.0/graphify/salesforce/__main__.py +8 -0
  42. graphify_sfdx-0.1.0/graphify/salesforce/apex_enhanced.py +324 -0
  43. graphify_sfdx-0.1.0/graphify/salesforce/cli.py +179 -0
  44. graphify_sfdx-0.1.0/graphify/salesforce/constants.py +143 -0
  45. graphify_sfdx-0.1.0/graphify/salesforce/cpq.py +168 -0
  46. graphify_sfdx-0.1.0/graphify/salesforce/cpq_data.py +298 -0
  47. graphify_sfdx-0.1.0/graphify/salesforce/flow.py +247 -0
  48. graphify_sfdx-0.1.0/graphify/salesforce/flow_cpq_loops.py +140 -0
  49. graphify_sfdx-0.1.0/graphify/salesforce/governor_limits.py +264 -0
  50. graphify_sfdx-0.1.0/graphify/salesforce/lwc.py +217 -0
  51. graphify_sfdx-0.1.0/graphify/salesforce/mdt_mapping.py +164 -0
  52. graphify_sfdx-0.1.0/graphify/salesforce/metadata.py +311 -0
  53. graphify_sfdx-0.1.0/graphify/salesforce/neo4j_sf.py +222 -0
  54. graphify_sfdx-0.1.0/graphify/salesforce/objects.py +430 -0
  55. graphify_sfdx-0.1.0/graphify/salesforce/order_of_execution.py +110 -0
  56. graphify_sfdx-0.1.0/graphify/salesforce/permission_analysis.py +109 -0
  57. graphify_sfdx-0.1.0/graphify/salesforce/pipeline.py +89 -0
  58. graphify_sfdx-0.1.0/graphify/salesforce/profiles.py +193 -0
  59. graphify_sfdx-0.1.0/graphify/salesforce/query.py +252 -0
  60. graphify_sfdx-0.1.0/graphify/salesforce/release_sync.py +136 -0
  61. graphify_sfdx-0.1.0/graphify/salesforce/validate_sf.py +193 -0
  62. graphify_sfdx-0.1.0/graphify/salesforce/validation_cpq.py +175 -0
  63. graphify_sfdx-0.1.0/graphify/salesforce/viz.py +139 -0
  64. graphify_sfdx-0.1.0/graphify/scip_ingest.py +363 -0
  65. graphify_sfdx-0.1.0/graphify/security.py +457 -0
  66. graphify_sfdx-0.1.0/graphify/semantic_cleanup.py +319 -0
  67. graphify_sfdx-0.1.0/graphify/serve.py +1394 -0
  68. graphify_sfdx-0.1.0/graphify/skill-aider.md +1245 -0
  69. graphify_sfdx-0.1.0/graphify/skill-amp.md +614 -0
  70. graphify_sfdx-0.1.0/graphify/skill-claw.md +617 -0
  71. graphify_sfdx-0.1.0/graphify/skill-codex.md +614 -0
  72. graphify_sfdx-0.1.0/graphify/skill-copilot.md +617 -0
  73. graphify_sfdx-0.1.0/graphify/skill-devin.md +1372 -0
  74. graphify_sfdx-0.1.0/graphify/skill-droid.md +614 -0
  75. graphify_sfdx-0.1.0/graphify/skill-kilo.md +626 -0
  76. graphify_sfdx-0.1.0/graphify/skill-kiro.md +617 -0
  77. graphify_sfdx-0.1.0/graphify/skill-opencode.md +609 -0
  78. graphify_sfdx-0.1.0/graphify/skill-pi.md +617 -0
  79. graphify_sfdx-0.1.0/graphify/skill-trae.md +615 -0
  80. graphify_sfdx-0.1.0/graphify/skill-vscode.md +613 -0
  81. graphify_sfdx-0.1.0/graphify/skill-windows.md +652 -0
  82. graphify_sfdx-0.1.0/graphify/skill.md +617 -0
  83. graphify_sfdx-0.1.0/graphify/skills/amp/references/add-watch.md +56 -0
  84. graphify_sfdx-0.1.0/graphify/skills/amp/references/exports.md +87 -0
  85. graphify_sfdx-0.1.0/graphify/skills/amp/references/extraction-spec.md +68 -0
  86. graphify_sfdx-0.1.0/graphify/skills/amp/references/github-and-merge.md +46 -0
  87. graphify_sfdx-0.1.0/graphify/skills/amp/references/hooks.md +33 -0
  88. graphify_sfdx-0.1.0/graphify/skills/amp/references/query.md +303 -0
  89. graphify_sfdx-0.1.0/graphify/skills/amp/references/transcribe.md +48 -0
  90. graphify_sfdx-0.1.0/graphify/skills/amp/references/update.md +179 -0
  91. graphify_sfdx-0.1.0/graphify/skills/claude/references/add-watch.md +56 -0
  92. graphify_sfdx-0.1.0/graphify/skills/claude/references/exports.md +87 -0
  93. graphify_sfdx-0.1.0/graphify/skills/claude/references/extraction-spec.md +68 -0
  94. graphify_sfdx-0.1.0/graphify/skills/claude/references/github-and-merge.md +46 -0
  95. graphify_sfdx-0.1.0/graphify/skills/claude/references/hooks.md +33 -0
  96. graphify_sfdx-0.1.0/graphify/skills/claude/references/query.md +303 -0
  97. graphify_sfdx-0.1.0/graphify/skills/claude/references/transcribe.md +48 -0
  98. graphify_sfdx-0.1.0/graphify/skills/claude/references/update.md +179 -0
  99. graphify_sfdx-0.1.0/graphify/skills/claw/references/add-watch.md +56 -0
  100. graphify_sfdx-0.1.0/graphify/skills/claw/references/exports.md +87 -0
  101. graphify_sfdx-0.1.0/graphify/skills/claw/references/extraction-spec.md +29 -0
  102. graphify_sfdx-0.1.0/graphify/skills/claw/references/github-and-merge.md +46 -0
  103. graphify_sfdx-0.1.0/graphify/skills/claw/references/hooks.md +33 -0
  104. graphify_sfdx-0.1.0/graphify/skills/claw/references/query.md +303 -0
  105. graphify_sfdx-0.1.0/graphify/skills/claw/references/transcribe.md +48 -0
  106. graphify_sfdx-0.1.0/graphify/skills/claw/references/update.md +179 -0
  107. graphify_sfdx-0.1.0/graphify/skills/codex/references/add-watch.md +56 -0
  108. graphify_sfdx-0.1.0/graphify/skills/codex/references/exports.md +87 -0
  109. graphify_sfdx-0.1.0/graphify/skills/codex/references/extraction-spec.md +29 -0
  110. graphify_sfdx-0.1.0/graphify/skills/codex/references/github-and-merge.md +46 -0
  111. graphify_sfdx-0.1.0/graphify/skills/codex/references/hooks.md +33 -0
  112. graphify_sfdx-0.1.0/graphify/skills/codex/references/query.md +303 -0
  113. graphify_sfdx-0.1.0/graphify/skills/codex/references/transcribe.md +48 -0
  114. graphify_sfdx-0.1.0/graphify/skills/codex/references/update.md +179 -0
  115. graphify_sfdx-0.1.0/graphify/skills/copilot/references/add-watch.md +56 -0
  116. graphify_sfdx-0.1.0/graphify/skills/copilot/references/exports.md +87 -0
  117. graphify_sfdx-0.1.0/graphify/skills/copilot/references/extraction-spec.md +68 -0
  118. graphify_sfdx-0.1.0/graphify/skills/copilot/references/github-and-merge.md +46 -0
  119. graphify_sfdx-0.1.0/graphify/skills/copilot/references/hooks.md +33 -0
  120. graphify_sfdx-0.1.0/graphify/skills/copilot/references/query.md +303 -0
  121. graphify_sfdx-0.1.0/graphify/skills/copilot/references/transcribe.md +48 -0
  122. graphify_sfdx-0.1.0/graphify/skills/copilot/references/update.md +179 -0
  123. graphify_sfdx-0.1.0/graphify/skills/droid/references/add-watch.md +56 -0
  124. graphify_sfdx-0.1.0/graphify/skills/droid/references/exports.md +87 -0
  125. graphify_sfdx-0.1.0/graphify/skills/droid/references/extraction-spec.md +68 -0
  126. graphify_sfdx-0.1.0/graphify/skills/droid/references/github-and-merge.md +46 -0
  127. graphify_sfdx-0.1.0/graphify/skills/droid/references/hooks.md +33 -0
  128. graphify_sfdx-0.1.0/graphify/skills/droid/references/query.md +303 -0
  129. graphify_sfdx-0.1.0/graphify/skills/droid/references/transcribe.md +48 -0
  130. graphify_sfdx-0.1.0/graphify/skills/droid/references/update.md +179 -0
  131. graphify_sfdx-0.1.0/graphify/skills/kilo/references/add-watch.md +56 -0
  132. graphify_sfdx-0.1.0/graphify/skills/kilo/references/exports.md +87 -0
  133. graphify_sfdx-0.1.0/graphify/skills/kilo/references/extraction-spec.md +68 -0
  134. graphify_sfdx-0.1.0/graphify/skills/kilo/references/github-and-merge.md +46 -0
  135. graphify_sfdx-0.1.0/graphify/skills/kilo/references/hooks.md +33 -0
  136. graphify_sfdx-0.1.0/graphify/skills/kilo/references/query.md +303 -0
  137. graphify_sfdx-0.1.0/graphify/skills/kilo/references/transcribe.md +48 -0
  138. graphify_sfdx-0.1.0/graphify/skills/kilo/references/update.md +179 -0
  139. graphify_sfdx-0.1.0/graphify/skills/kiro/references/add-watch.md +56 -0
  140. graphify_sfdx-0.1.0/graphify/skills/kiro/references/exports.md +87 -0
  141. graphify_sfdx-0.1.0/graphify/skills/kiro/references/extraction-spec.md +29 -0
  142. graphify_sfdx-0.1.0/graphify/skills/kiro/references/github-and-merge.md +46 -0
  143. graphify_sfdx-0.1.0/graphify/skills/kiro/references/hooks.md +33 -0
  144. graphify_sfdx-0.1.0/graphify/skills/kiro/references/query.md +303 -0
  145. graphify_sfdx-0.1.0/graphify/skills/kiro/references/transcribe.md +48 -0
  146. graphify_sfdx-0.1.0/graphify/skills/kiro/references/update.md +179 -0
  147. graphify_sfdx-0.1.0/graphify/skills/opencode/references/add-watch.md +56 -0
  148. graphify_sfdx-0.1.0/graphify/skills/opencode/references/exports.md +87 -0
  149. graphify_sfdx-0.1.0/graphify/skills/opencode/references/extraction-spec.md +68 -0
  150. graphify_sfdx-0.1.0/graphify/skills/opencode/references/github-and-merge.md +46 -0
  151. graphify_sfdx-0.1.0/graphify/skills/opencode/references/hooks.md +33 -0
  152. graphify_sfdx-0.1.0/graphify/skills/opencode/references/query.md +303 -0
  153. graphify_sfdx-0.1.0/graphify/skills/opencode/references/transcribe.md +48 -0
  154. graphify_sfdx-0.1.0/graphify/skills/opencode/references/update.md +179 -0
  155. graphify_sfdx-0.1.0/graphify/skills/pi/references/add-watch.md +56 -0
  156. graphify_sfdx-0.1.0/graphify/skills/pi/references/exports.md +87 -0
  157. graphify_sfdx-0.1.0/graphify/skills/pi/references/extraction-spec.md +29 -0
  158. graphify_sfdx-0.1.0/graphify/skills/pi/references/github-and-merge.md +46 -0
  159. graphify_sfdx-0.1.0/graphify/skills/pi/references/hooks.md +33 -0
  160. graphify_sfdx-0.1.0/graphify/skills/pi/references/query.md +303 -0
  161. graphify_sfdx-0.1.0/graphify/skills/pi/references/transcribe.md +48 -0
  162. graphify_sfdx-0.1.0/graphify/skills/pi/references/update.md +179 -0
  163. graphify_sfdx-0.1.0/graphify/skills/trae/references/add-watch.md +56 -0
  164. graphify_sfdx-0.1.0/graphify/skills/trae/references/exports.md +87 -0
  165. graphify_sfdx-0.1.0/graphify/skills/trae/references/extraction-spec.md +68 -0
  166. graphify_sfdx-0.1.0/graphify/skills/trae/references/github-and-merge.md +46 -0
  167. graphify_sfdx-0.1.0/graphify/skills/trae/references/hooks.md +35 -0
  168. graphify_sfdx-0.1.0/graphify/skills/trae/references/query.md +303 -0
  169. graphify_sfdx-0.1.0/graphify/skills/trae/references/transcribe.md +48 -0
  170. graphify_sfdx-0.1.0/graphify/skills/trae/references/update.md +179 -0
  171. graphify_sfdx-0.1.0/graphify/skills/vscode/references/add-watch.md +56 -0
  172. graphify_sfdx-0.1.0/graphify/skills/vscode/references/exports.md +87 -0
  173. graphify_sfdx-0.1.0/graphify/skills/vscode/references/extraction-spec.md +68 -0
  174. graphify_sfdx-0.1.0/graphify/skills/vscode/references/github-and-merge.md +46 -0
  175. graphify_sfdx-0.1.0/graphify/skills/vscode/references/hooks.md +33 -0
  176. graphify_sfdx-0.1.0/graphify/skills/vscode/references/query.md +303 -0
  177. graphify_sfdx-0.1.0/graphify/skills/vscode/references/transcribe.md +48 -0
  178. graphify_sfdx-0.1.0/graphify/skills/vscode/references/update.md +179 -0
  179. graphify_sfdx-0.1.0/graphify/skills/windows/references/add-watch.md +56 -0
  180. graphify_sfdx-0.1.0/graphify/skills/windows/references/exports.md +87 -0
  181. graphify_sfdx-0.1.0/graphify/skills/windows/references/extraction-spec.md +68 -0
  182. graphify_sfdx-0.1.0/graphify/skills/windows/references/github-and-merge.md +46 -0
  183. graphify_sfdx-0.1.0/graphify/skills/windows/references/hooks.md +33 -0
  184. graphify_sfdx-0.1.0/graphify/skills/windows/references/query.md +303 -0
  185. graphify_sfdx-0.1.0/graphify/skills/windows/references/transcribe.md +48 -0
  186. graphify_sfdx-0.1.0/graphify/skills/windows/references/update.md +179 -0
  187. graphify_sfdx-0.1.0/graphify/symbol_resolution.py +538 -0
  188. graphify_sfdx-0.1.0/graphify/transcribe.py +184 -0
  189. graphify_sfdx-0.1.0/graphify/tree_html.py +582 -0
  190. graphify_sfdx-0.1.0/graphify/validate.py +79 -0
  191. graphify_sfdx-0.1.0/graphify/watch.py +908 -0
  192. graphify_sfdx-0.1.0/graphify/wiki.py +282 -0
  193. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/PKG-INFO +345 -0
  194. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/SOURCES.txt +287 -0
  195. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/dependency_links.txt +1 -0
  196. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/entry_points.txt +5 -0
  197. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/requires.txt +134 -0
  198. graphify_sfdx-0.1.0/graphify_sfdx.egg-info/top_level.txt +1 -0
  199. graphify_sfdx-0.1.0/pyproject.toml +146 -0
  200. graphify_sfdx-0.1.0/setup.cfg +4 -0
  201. graphify_sfdx-0.1.0/tests/test_affected_cli.py +155 -0
  202. graphify_sfdx-0.1.0/tests/test_analyze.py +723 -0
  203. graphify_sfdx-0.1.0/tests/test_anthropic_custom_endpoint.py +34 -0
  204. graphify_sfdx-0.1.0/tests/test_antigravity_install.py +28 -0
  205. graphify_sfdx-0.1.0/tests/test_astro_extraction.py +143 -0
  206. graphify_sfdx-0.1.0/tests/test_backend_extras.py +41 -0
  207. graphify_sfdx-0.1.0/tests/test_benchmark.py +183 -0
  208. graphify_sfdx-0.1.0/tests/test_build.py +561 -0
  209. graphify_sfdx-0.1.0/tests/test_cache.py +422 -0
  210. graphify_sfdx-0.1.0/tests/test_callflow_html.py +187 -0
  211. graphify_sfdx-0.1.0/tests/test_cargo_introspect.py +365 -0
  212. graphify_sfdx-0.1.0/tests/test_charmap_encoding.py +330 -0
  213. graphify_sfdx-0.1.0/tests/test_chunking.py +452 -0
  214. graphify_sfdx-0.1.0/tests/test_claude_cli_backend.py +257 -0
  215. graphify_sfdx-0.1.0/tests/test_claude_md.py +136 -0
  216. graphify_sfdx-0.1.0/tests/test_cli_export.py +436 -0
  217. graphify_sfdx-0.1.0/tests/test_cluster.py +100 -0
  218. graphify_sfdx-0.1.0/tests/test_codebuddy.py +341 -0
  219. graphify_sfdx-0.1.0/tests/test_confidence.py +192 -0
  220. graphify_sfdx-0.1.0/tests/test_cpp_preprocess.py +32 -0
  221. graphify_sfdx-0.1.0/tests/test_dart.py +640 -0
  222. graphify_sfdx-0.1.0/tests/test_dedup.py +270 -0
  223. graphify_sfdx-0.1.0/tests/test_detect.py +1494 -0
  224. graphify_sfdx-0.1.0/tests/test_devin.py +309 -0
  225. graphify_sfdx-0.1.0/tests/test_dotnet.py +160 -0
  226. graphify_sfdx-0.1.0/tests/test_explain_cli.py +56 -0
  227. graphify_sfdx-0.1.0/tests/test_export.py +263 -0
  228. graphify_sfdx-0.1.0/tests/test_extract.py +1300 -0
  229. graphify_sfdx-0.1.0/tests/test_extract_cli.py +237 -0
  230. graphify_sfdx-0.1.0/tests/test_falkordb_integration.py +91 -0
  231. graphify_sfdx-0.1.0/tests/test_file_node_id_spec.py +151 -0
  232. graphify_sfdx-0.1.0/tests/test_global_graph.py +339 -0
  233. graphify_sfdx-0.1.0/tests/test_google_workspace.py +129 -0
  234. graphify_sfdx-0.1.0/tests/test_hooks.py +335 -0
  235. graphify_sfdx-0.1.0/tests/test_hypergraph.py +205 -0
  236. graphify_sfdx-0.1.0/tests/test_image_vision.py +345 -0
  237. graphify_sfdx-0.1.0/tests/test_import_extension_resolution.py +529 -0
  238. graphify_sfdx-0.1.0/tests/test_incremental.py +74 -0
  239. graphify_sfdx-0.1.0/tests/test_ingest.py +68 -0
  240. graphify_sfdx-0.1.0/tests/test_install.py +972 -0
  241. graphify_sfdx-0.1.0/tests/test_install_references.py +516 -0
  242. graphify_sfdx-0.1.0/tests/test_install_roundtrip.py +318 -0
  243. graphify_sfdx-0.1.0/tests/test_install_strings.py +135 -0
  244. graphify_sfdx-0.1.0/tests/test_install_upgrade.py +272 -0
  245. graphify_sfdx-0.1.0/tests/test_java_type_resolution.py +100 -0
  246. graphify_sfdx-0.1.0/tests/test_js_import_resolution.py +565 -0
  247. graphify_sfdx-0.1.0/tests/test_labeling.py +280 -0
  248. graphify_sfdx-0.1.0/tests/test_languages.py +1718 -0
  249. graphify_sfdx-0.1.0/tests/test_llm_backends.py +748 -0
  250. graphify_sfdx-0.1.0/tests/test_llm_parser.py +146 -0
  251. graphify_sfdx-0.1.0/tests/test_mcp_ingest.py +331 -0
  252. graphify_sfdx-0.1.0/tests/test_minhash.py +101 -0
  253. graphify_sfdx-0.1.0/tests/test_multigraph_compat.py +56 -0
  254. graphify_sfdx-0.1.0/tests/test_multigraph_diagnostics.py +460 -0
  255. graphify_sfdx-0.1.0/tests/test_multilang.py +489 -0
  256. graphify_sfdx-0.1.0/tests/test_obsidian_dangling_member.py +50 -0
  257. graphify_sfdx-0.1.0/tests/test_obsidian_filename_cap.py +73 -0
  258. graphify_sfdx-0.1.0/tests/test_office_limits.py +90 -0
  259. graphify_sfdx-0.1.0/tests/test_ollama.py +118 -0
  260. graphify_sfdx-0.1.0/tests/test_openai_custom_endpoint.py +46 -0
  261. graphify_sfdx-0.1.0/tests/test_pascal.py +322 -0
  262. graphify_sfdx-0.1.0/tests/test_path_cli.py +48 -0
  263. graphify_sfdx-0.1.0/tests/test_pg_introspect.py +278 -0
  264. graphify_sfdx-0.1.0/tests/test_pipeline.py +158 -0
  265. graphify_sfdx-0.1.0/tests/test_provider_registry.py +164 -0
  266. graphify_sfdx-0.1.0/tests/test_prs.py +403 -0
  267. graphify_sfdx-0.1.0/tests/test_python_import_resolution.py +86 -0
  268. graphify_sfdx-0.1.0/tests/test_query_cli.py +70 -0
  269. graphify_sfdx-0.1.0/tests/test_querylog.py +178 -0
  270. graphify_sfdx-0.1.0/tests/test_rationale.py +263 -0
  271. graphify_sfdx-0.1.0/tests/test_read_hook.py +80 -0
  272. graphify_sfdx-0.1.0/tests/test_report.py +63 -0
  273. graphify_sfdx-0.1.0/tests/test_salesforce.py +1918 -0
  274. graphify_sfdx-0.1.0/tests/test_scip_ingest.py +1670 -0
  275. graphify_sfdx-0.1.0/tests/test_security.py +383 -0
  276. graphify_sfdx-0.1.0/tests/test_semantic_cleanup.py +344 -0
  277. graphify_sfdx-0.1.0/tests/test_semantic_similarity.py +194 -0
  278. graphify_sfdx-0.1.0/tests/test_serve.py +572 -0
  279. graphify_sfdx-0.1.0/tests/test_serve_http.py +232 -0
  280. graphify_sfdx-0.1.0/tests/test_skillgen.py +796 -0
  281. graphify_sfdx-0.1.0/tests/test_swift_import_resolution.py +85 -0
  282. graphify_sfdx-0.1.0/tests/test_symbol_resolution.py +1019 -0
  283. graphify_sfdx-0.1.0/tests/test_terraform.py +158 -0
  284. graphify_sfdx-0.1.0/tests/test_transcribe.py +147 -0
  285. graphify_sfdx-0.1.0/tests/test_ts_inheritance.py +91 -0
  286. graphify_sfdx-0.1.0/tests/test_validate.py +87 -0
  287. graphify_sfdx-0.1.0/tests/test_watch.py +864 -0
  288. graphify_sfdx-0.1.0/tests/test_wheel_packaging.py +71 -0
  289. graphify_sfdx-0.1.0/tests/test_wiki.py +212 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Safi Shamsi
4
+ Copyright (c) 2026 JeremyKo95
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ graphify-sf is a derivative work based on "graphify"
2
+ (https://github.com/safishamsi/graphify), originally licensed under MIT.
3
+
4
+ Original work: Copyright (c) 2026 Safi Shamsi
5
+ Modifications: Copyright (c) 2026 JeremyKo95 <sukun9512@gmail.com>
6
+
7
+ Salesforce-specific adaptations (LWC/Apex/CPQ/Governor Limit handling)
8
+ are contributed by JeremyKo95.
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: graphify-sfdx
3
+ Version: 0.1.0
4
+ Summary: Salesforce-aware knowledge graph: parse SFDX metadata (Apex, Flow, LWC, CPQ, Governor Limits, Order-of-Execution) into a queryable NetworkX graph — fully offline, no org connection required.
5
+ Author-email: JeremyKo95 <sukun9512@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Safi Shamsi
9
+ Copyright (c) 2026 JeremyKo95
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/JeremyKo95/graphify-sf
30
+ Project-URL: Repository, https://github.com/JeremyKo95/graphify-sf
31
+ Project-URL: Issues, https://github.com/JeremyKo95/graphify-sf/issues
32
+ Keywords: salesforce,sfdx,apex,flow,lwc,cpq,governor-limits,knowledge-graph,rag,graphrag,community-detection,tree-sitter,leiden,mcp
33
+ Requires-Python: >=3.10
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ License-File: NOTICE
37
+ Requires-Dist: networkx>=3.4
38
+ Requires-Dist: numpy>=1.21
39
+ Requires-Dist: rapidfuzz>=3.0
40
+ Requires-Dist: tree-sitter<0.26,>=0.23.0
41
+ Requires-Dist: tree-sitter-python<0.26,>=0.23
42
+ Requires-Dist: tree-sitter-javascript<0.26,>=0.23
43
+ Requires-Dist: tree-sitter-typescript<0.25,>=0.23
44
+ Requires-Dist: tree-sitter-go<0.26,>=0.23
45
+ Requires-Dist: tree-sitter-rust<0.25,>=0.23
46
+ Requires-Dist: tree-sitter-java<0.25,>=0.23
47
+ Requires-Dist: tree-sitter-groovy<0.3,>=0.1
48
+ Requires-Dist: tree-sitter-c<0.25,>=0.23
49
+ Requires-Dist: tree-sitter-cpp<0.25,>=0.23
50
+ Requires-Dist: tree-sitter-ruby<0.25,>=0.23
51
+ Requires-Dist: tree-sitter-c-sharp<0.25,>=0.23
52
+ Requires-Dist: tree-sitter-kotlin<2.0,>=1.0
53
+ Requires-Dist: tree-sitter-scala<0.27,>=0.23
54
+ Requires-Dist: tree-sitter-php<0.25,>=0.23
55
+ Requires-Dist: tree-sitter-swift<0.9,>=0.7
56
+ Requires-Dist: tree-sitter-lua<0.6,>=0.2
57
+ Requires-Dist: tree-sitter-zig<2.0,>=1.0
58
+ Requires-Dist: tree-sitter-powershell<0.28,>=0.26
59
+ Requires-Dist: tree-sitter-elixir<0.5,>=0.3
60
+ Requires-Dist: tree-sitter-objc<4.0,>=3.0
61
+ Requires-Dist: tree-sitter-julia<0.25,>=0.23
62
+ Requires-Dist: tree-sitter-verilog<2.0,>=1.0
63
+ Requires-Dist: tree-sitter-fortran<0.8,>=0.6
64
+ Requires-Dist: tree-sitter-bash<0.27,>=0.23
65
+ Requires-Dist: tree-sitter-json<0.26,>=0.23
66
+ Provides-Extra: mcp
67
+ Requires-Dist: mcp; extra == "mcp"
68
+ Provides-Extra: neo4j
69
+ Requires-Dist: neo4j; extra == "neo4j"
70
+ Provides-Extra: falkordb
71
+ Requires-Dist: falkordb; extra == "falkordb"
72
+ Provides-Extra: pdf
73
+ Requires-Dist: pypdf; extra == "pdf"
74
+ Requires-Dist: markdownify; extra == "pdf"
75
+ Provides-Extra: watch
76
+ Requires-Dist: watchdog; extra == "watch"
77
+ Provides-Extra: svg
78
+ Requires-Dist: matplotlib; extra == "svg"
79
+ Requires-Dist: numpy>=2.0; python_version >= "3.13" and extra == "svg"
80
+ Provides-Extra: leiden
81
+ Requires-Dist: graspologic; python_version < "3.13" and extra == "leiden"
82
+ Provides-Extra: office
83
+ Requires-Dist: python-docx; extra == "office"
84
+ Requires-Dist: openpyxl; extra == "office"
85
+ Provides-Extra: google
86
+ Requires-Dist: openpyxl; extra == "google"
87
+ Provides-Extra: postgres
88
+ Requires-Dist: psycopg[binary]; extra == "postgres"
89
+ Provides-Extra: video
90
+ Requires-Dist: faster-whisper; python_version >= "3.11" and extra == "video"
91
+ Requires-Dist: yt-dlp; extra == "video"
92
+ Provides-Extra: kimi
93
+ Requires-Dist: openai; extra == "kimi"
94
+ Requires-Dist: tiktoken; extra == "kimi"
95
+ Provides-Extra: ollama
96
+ Requires-Dist: openai; extra == "ollama"
97
+ Provides-Extra: bedrock
98
+ Requires-Dist: boto3; extra == "bedrock"
99
+ Provides-Extra: anthropic
100
+ Requires-Dist: anthropic; extra == "anthropic"
101
+ Provides-Extra: gemini
102
+ Requires-Dist: openai; extra == "gemini"
103
+ Requires-Dist: tiktoken; extra == "gemini"
104
+ Provides-Extra: openai
105
+ Requires-Dist: openai; extra == "openai"
106
+ Requires-Dist: tiktoken; extra == "openai"
107
+ Provides-Extra: chinese
108
+ Requires-Dist: jieba; extra == "chinese"
109
+ Provides-Extra: sql
110
+ Requires-Dist: tree-sitter-sql; extra == "sql"
111
+ Provides-Extra: dm
112
+ Requires-Dist: tree-sitter-dm; extra == "dm"
113
+ Provides-Extra: terraform
114
+ Requires-Dist: tree-sitter-hcl; extra == "terraform"
115
+ Provides-Extra: all
116
+ Requires-Dist: mcp; extra == "all"
117
+ Requires-Dist: neo4j; extra == "all"
118
+ Requires-Dist: falkordb; extra == "all"
119
+ Requires-Dist: pypdf; extra == "all"
120
+ Requires-Dist: markdownify; extra == "all"
121
+ Requires-Dist: watchdog; extra == "all"
122
+ Requires-Dist: graspologic; python_version < "3.13" and extra == "all"
123
+ Requires-Dist: python-docx; extra == "all"
124
+ Requires-Dist: openpyxl; extra == "all"
125
+ Requires-Dist: faster-whisper; python_version >= "3.11" and extra == "all"
126
+ Requires-Dist: yt-dlp; extra == "all"
127
+ Requires-Dist: matplotlib; extra == "all"
128
+ Requires-Dist: numpy>=2.0; python_version >= "3.13" and extra == "all"
129
+ Requires-Dist: openai; extra == "all"
130
+ Requires-Dist: tiktoken; extra == "all"
131
+ Requires-Dist: boto3; extra == "all"
132
+ Requires-Dist: anthropic; extra == "all"
133
+ Requires-Dist: tree-sitter-sql; extra == "all"
134
+ Requires-Dist: jieba; extra == "all"
135
+ Requires-Dist: tree-sitter-dm; extra == "all"
136
+ Requires-Dist: tree-sitter-hcl; extra == "all"
137
+ Dynamic: license-file
138
+
139
+ # graphify-sf
140
+
141
+ > ⚡ A **Salesforce-native** knowledge-graph library — turn any Enterprise (CPQ)
142
+ > Salesforce org's metadata into a token-minimized graph for onboarding, analysis,
143
+ > impact review, and development.
144
+ > Inspired by [graphify](https://github.com/safishamsi/graphify); rebuilt in Python
145
+ > for Apex, Flow, LWC, CPQ data, and the realities of Governor Limits.
146
+
147
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
148
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](#)
149
+
150
+ ---
151
+
152
+ ## What it is
153
+
154
+ `graphify-sf` is a **Python library** (not an on-platform package). It statically
155
+ parses a Salesforce metadata repository — and CPQ rule **data** — into a NetworkX
156
+ knowledge graph, runs Salesforce-aware analysis passes, then serves a
157
+ **token-minimized** view so an LLM (or a person) can answer "what breaks if I change
158
+ X?", "how is a Quote created from an Opportunity?", or "where are the Governor-Limit
159
+ risks?" without reading the raw org.
160
+
161
+ The North Star: **any Enterprise CPQ org → SF-specific KB graph → token-minimized
162
+ consumption → onboarding, analysis, impact review, and development.**
163
+
164
+ ## Capabilities
165
+
166
+ - **Parsers** (`graphify/salesforce/`): Apex (regex, ADR-019), Flow (typed record
167
+ tags), LWC (`@wire` + imperative Apex), Custom Object/Field, Profile/Permission Set,
168
+ Validation Rule, Record Type, Permission Set Group, Workflow, **Custom Metadata
169
+ records, Sharing Rules, Custom Labels, Custom Settings**.
170
+ - **CPQ rule data ingest** (`cpq_data.py`): SBQQ Price/Product Rules, Conditions,
171
+ Actions from **SFDX JSON or Gearset `*.gs.json`**, plus **JavaScript QCP** custom
172
+ scripts — the logic that lives as data records, not metadata.
173
+ - **`__mdt` field mappings** (`mdt_mapping.py`): turns mapping records (e.g.
174
+ `Opportunity_To_Quote_Mapping__mdt`) into traversable `maps_to` field→field edges so
175
+ impact follows the Opp→Quote boundary.
176
+ - **Analysis passes** (whole-graph): Order of Execution, Governor Limits, recursive
177
+ triggers, Profile/FLS permission impact, Flow↔CPQ infinite loops, CPQ↔Validation
178
+ Rule conflicts.
179
+ - **Token-minimized consumption** (`pipeline.py`/`query.py`/`cli.py`/`viz.py`): Leiden
180
+ community clustering, `token_budget`-bounded queries, an MCP server, and a focused
181
+ self-contained HTML visualization.
182
+
183
+ Every node/edge carries a `confidence` (EXTRACTED / INFERRED / AMBIGUOUS) so you know
184
+ what is certain vs. heuristic. See [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md),
185
+ [`docs/ADR.md`](./docs/ADR.md), and [`docs/PRD.md`](./docs/PRD.md).
186
+
187
+ ## Install
188
+
189
+ ```bash
190
+ pip install -e .
191
+ ```
192
+
193
+ Requires Python 3.11+. `networkx` is required; `graspologic` (Leiden), `mcp` (serve),
194
+ and `tree-sitter` are optional and degrade gracefully when absent.
195
+
196
+ ## Quick start
197
+
198
+ ```bash
199
+ # 1. Extract + enrich a graph (optionally merge CPQ rule data)
200
+ python -m graphify.salesforce extract path/to/sf-repo \
201
+ --output-dir graphify-out --cpq-data path/to/cpq-records
202
+
203
+ # 2. Ask SF-aware questions (token-bounded)
204
+ python -m graphify.salesforce impact <node-id> --direction downstream
205
+ python -m graphify.salesforce violations --severity HIGH
206
+ python -m graphify.salesforce cpq-chain SBQQ__Quote__c
207
+ python -m graphify.salesforce ooe Opportunity
208
+
209
+ # 3. Visualize a focused subgraph (self-contained HTML)
210
+ python -m graphify.salesforce viz graphify-out/graph.json --focus <node-id>
211
+
212
+ # 4. Serve over MCP for an LLM client
213
+ python -m graphify.serve graphify-out/graph.json
214
+ ```
215
+
216
+ Run the test suite with `pytest tests/test_salesforce.py -v`.
217
+
218
+ ## Use it from an AI agent (Claude, Copilot, Cursor, …)
219
+
220
+ The point of `graphify-sf` is that an agent answers Salesforce questions from the
221
+ **graph** instead of reading raw metadata — so it stays accurate and token-cheap. The
222
+ flow is always: **extract once → expose the graph → the agent queries it.**
223
+
224
+ ### Step 1 — build the graph (once per org snapshot)
225
+
226
+ ```bash
227
+ python -m graphify.salesforce extract path/to/sf-repo \
228
+ --output-dir graphify-out --cpq-data path/to/cpq-records
229
+ # → graphify-out/graph.json
230
+ ```
231
+
232
+ Re-run after a metadata pull to refresh it.
233
+
234
+ ### Option A — MCP server (recommended)
235
+
236
+ Serve the graph over MCP; the agent gets token-bounded Salesforce tools
237
+ (`sf_impact`, `sf_violations`, `sf_cpq_chain`, `sf_ooe`) plus the base graph tools
238
+ (`query_graph`, `graph_stats`, `god_nodes`, `shortest_path`, `get_neighbors`, …).
239
+
240
+ ```bash
241
+ # stdio transport (default — what desktop agents launch)
242
+ python -m graphify.serve graphify-out/graph.json
243
+ # or the console script after `pip install -e .`
244
+ graphify-mcp graphify-out/graph.json
245
+ # shared HTTP transport (team / remote)
246
+ python -m graphify.serve graphify-out/graph.json --transport http --port 8080
247
+ ```
248
+
249
+ **Claude Code** — one command (use an absolute path to `graph.json`):
250
+
251
+ ```bash
252
+ claude mcp add graphify-sf -- python -m graphify.serve /abs/path/to/graphify-out/graph.json
253
+ ```
254
+
255
+ **Claude Desktop / Cursor / Windsurf** — add to the MCP config
256
+ (`claude_desktop_config.json`, `.cursor/mcp.json`, …); they share this shape:
257
+
258
+ ```json
259
+ {
260
+ "mcpServers": {
261
+ "graphify-sf": {
262
+ "command": "python",
263
+ "args": ["-m", "graphify.serve", "/abs/path/to/graphify-out/graph.json"]
264
+ }
265
+ }
266
+ }
267
+ ```
268
+
269
+ **VS Code / GitHub Copilot** — `.vscode/mcp.json` uses the `servers` key:
270
+
271
+ ```json
272
+ {
273
+ "servers": {
274
+ "graphify-sf": {
275
+ "type": "stdio",
276
+ "command": "python",
277
+ "args": ["-m", "graphify.serve", "/abs/path/to/graphify-out/graph.json"]
278
+ }
279
+ }
280
+ }
281
+ ```
282
+
283
+ Then just ask, e.g. *"What breaks if I change `Opportunity.Amount`? Use graphify-sf."*
284
+
285
+ ### Option B — no MCP (CLI the agent shells out to)
286
+
287
+ For agents that run shell commands but have no MCP, point them at the CLI — each
288
+ command prints a token-bounded answer to stdout:
289
+
290
+ ```bash
291
+ python -m graphify.salesforce impact <node-id> --direction downstream
292
+ python -m graphify.salesforce violations --severity HIGH
293
+ python -m graphify.salesforce cpq-chain SBQQ__Quote__c
294
+ python -m graphify.salesforce ooe Opportunity
295
+ ```
296
+
297
+ ### Tell the agent to use it on every task
298
+
299
+ Drop a short rule into the agent's project-instructions file — `CLAUDE.md` (Claude
300
+ Code), `.github/copilot-instructions.md` (Copilot), `.cursorrules` (Cursor), or
301
+ `AGENTS.md`:
302
+
303
+ ```markdown
304
+ ## Salesforce knowledge graph
305
+ Before answering Salesforce impact / CPQ / Order-of-Execution / Governor-Limit
306
+ questions, consult the graphify-sf graph instead of reading raw metadata:
307
+ - If the `graphify-sf` MCP server is connected, call `sf_impact` / `sf_violations` /
308
+ `sf_cpq_chain` / `sf_ooe`.
309
+ - Otherwise run `python -m graphify.salesforce <impact|violations|cpq-chain|ooe> …`.
310
+ Rebuild it with `python -m graphify.salesforce extract <repo> --cpq-data <dir>`
311
+ after pulling fresh metadata.
312
+ ```
313
+
314
+ ## Coverage
315
+
316
+ | Area | Module | Status |
317
+ |---|---|---|
318
+ | Core parsers (Apex/Flow/LWC/Objects/Profiles) | `apex_enhanced`, `flow`, `lwc`, `objects`, `profiles` | ✅ |
319
+ | Metadata coverage (RecordType/PSG/Workflow/Custom Metadata/Sharing/Label/Setting) | `metadata`, `objects` | ✅ |
320
+ | CPQ rule data (SFDX + Gearset + JS QCP) | `cpq_data` | ✅ |
321
+ | `__mdt` field mapping (Opp→Quote) | `mdt_mapping` | ✅ |
322
+ | Token-minimized consumption (cluster/query/CLI/viz/MCP) | `pipeline`, `query`, `cli`, `viz` | ✅ |
323
+ | Neo4j export | `neo4j_sf` | ✅ |
324
+ | Apex cross-class call resolution | tree-sitter promotion | ⏸ deferred (ADR-019) |
325
+
326
+ ---
327
+
328
+ ## Inspiration & Credits
329
+
330
+ This project stands on the shoulders of [**graphify**](https://github.com/safishamsi/graphify)
331
+ by **[Safi Shamsi](https://github.com/safishamsi)**. The core idea, architecture, and
332
+ API ergonomics are theirs — `graphify-sf` is an independent, Salesforce-tailored
333
+ adaptation built with deep respect for the original work. If you need a
334
+ platform-agnostic solution, please use and support the upstream project.
335
+
336
+ > 본 프로젝트는 [graphify](https://github.com/safishamsi/graphify)의 아이디어와 아키텍처에서
337
+ > 출발했습니다. 핵심 개념에 대한 모든 공로는 원작자에게 있으며, `graphify-sf`는 이를 Salesforce
338
+ > 플랫폼(Apex/Flow/LWC/CPQ) 환경에 맞게 재구현한 독립적인 파생 프로젝트입니다. 원작자의 노고에
339
+ > 깊이 감사드립니다. 범용 환경이 필요하다면 원본 프로젝트를 사용하시길 권장합니다.
340
+
341
+ > The upstream project's original README is preserved in this repo as [`README.upstream.md`](./README.upstream.md).
342
+
343
+ ## License
344
+
345
+ MIT © Safi Shamsi (graphify) · MIT © JeremyKo95 (graphify-sf). See [LICENSE](./LICENSE).
@@ -0,0 +1,207 @@
1
+ # graphify-sf
2
+
3
+ > ⚡ A **Salesforce-native** knowledge-graph library — turn any Enterprise (CPQ)
4
+ > Salesforce org's metadata into a token-minimized graph for onboarding, analysis,
5
+ > impact review, and development.
6
+ > Inspired by [graphify](https://github.com/safishamsi/graphify); rebuilt in Python
7
+ > for Apex, Flow, LWC, CPQ data, and the realities of Governor Limits.
8
+
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)
10
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](#)
11
+
12
+ ---
13
+
14
+ ## What it is
15
+
16
+ `graphify-sf` is a **Python library** (not an on-platform package). It statically
17
+ parses a Salesforce metadata repository — and CPQ rule **data** — into a NetworkX
18
+ knowledge graph, runs Salesforce-aware analysis passes, then serves a
19
+ **token-minimized** view so an LLM (or a person) can answer "what breaks if I change
20
+ X?", "how is a Quote created from an Opportunity?", or "where are the Governor-Limit
21
+ risks?" without reading the raw org.
22
+
23
+ The North Star: **any Enterprise CPQ org → SF-specific KB graph → token-minimized
24
+ consumption → onboarding, analysis, impact review, and development.**
25
+
26
+ ## Capabilities
27
+
28
+ - **Parsers** (`graphify/salesforce/`): Apex (regex, ADR-019), Flow (typed record
29
+ tags), LWC (`@wire` + imperative Apex), Custom Object/Field, Profile/Permission Set,
30
+ Validation Rule, Record Type, Permission Set Group, Workflow, **Custom Metadata
31
+ records, Sharing Rules, Custom Labels, Custom Settings**.
32
+ - **CPQ rule data ingest** (`cpq_data.py`): SBQQ Price/Product Rules, Conditions,
33
+ Actions from **SFDX JSON or Gearset `*.gs.json`**, plus **JavaScript QCP** custom
34
+ scripts — the logic that lives as data records, not metadata.
35
+ - **`__mdt` field mappings** (`mdt_mapping.py`): turns mapping records (e.g.
36
+ `Opportunity_To_Quote_Mapping__mdt`) into traversable `maps_to` field→field edges so
37
+ impact follows the Opp→Quote boundary.
38
+ - **Analysis passes** (whole-graph): Order of Execution, Governor Limits, recursive
39
+ triggers, Profile/FLS permission impact, Flow↔CPQ infinite loops, CPQ↔Validation
40
+ Rule conflicts.
41
+ - **Token-minimized consumption** (`pipeline.py`/`query.py`/`cli.py`/`viz.py`): Leiden
42
+ community clustering, `token_budget`-bounded queries, an MCP server, and a focused
43
+ self-contained HTML visualization.
44
+
45
+ Every node/edge carries a `confidence` (EXTRACTED / INFERRED / AMBIGUOUS) so you know
46
+ what is certain vs. heuristic. See [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md),
47
+ [`docs/ADR.md`](./docs/ADR.md), and [`docs/PRD.md`](./docs/PRD.md).
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install -e .
53
+ ```
54
+
55
+ Requires Python 3.11+. `networkx` is required; `graspologic` (Leiden), `mcp` (serve),
56
+ and `tree-sitter` are optional and degrade gracefully when absent.
57
+
58
+ ## Quick start
59
+
60
+ ```bash
61
+ # 1. Extract + enrich a graph (optionally merge CPQ rule data)
62
+ python -m graphify.salesforce extract path/to/sf-repo \
63
+ --output-dir graphify-out --cpq-data path/to/cpq-records
64
+
65
+ # 2. Ask SF-aware questions (token-bounded)
66
+ python -m graphify.salesforce impact <node-id> --direction downstream
67
+ python -m graphify.salesforce violations --severity HIGH
68
+ python -m graphify.salesforce cpq-chain SBQQ__Quote__c
69
+ python -m graphify.salesforce ooe Opportunity
70
+
71
+ # 3. Visualize a focused subgraph (self-contained HTML)
72
+ python -m graphify.salesforce viz graphify-out/graph.json --focus <node-id>
73
+
74
+ # 4. Serve over MCP for an LLM client
75
+ python -m graphify.serve graphify-out/graph.json
76
+ ```
77
+
78
+ Run the test suite with `pytest tests/test_salesforce.py -v`.
79
+
80
+ ## Use it from an AI agent (Claude, Copilot, Cursor, …)
81
+
82
+ The point of `graphify-sf` is that an agent answers Salesforce questions from the
83
+ **graph** instead of reading raw metadata — so it stays accurate and token-cheap. The
84
+ flow is always: **extract once → expose the graph → the agent queries it.**
85
+
86
+ ### Step 1 — build the graph (once per org snapshot)
87
+
88
+ ```bash
89
+ python -m graphify.salesforce extract path/to/sf-repo \
90
+ --output-dir graphify-out --cpq-data path/to/cpq-records
91
+ # → graphify-out/graph.json
92
+ ```
93
+
94
+ Re-run after a metadata pull to refresh it.
95
+
96
+ ### Option A — MCP server (recommended)
97
+
98
+ Serve the graph over MCP; the agent gets token-bounded Salesforce tools
99
+ (`sf_impact`, `sf_violations`, `sf_cpq_chain`, `sf_ooe`) plus the base graph tools
100
+ (`query_graph`, `graph_stats`, `god_nodes`, `shortest_path`, `get_neighbors`, …).
101
+
102
+ ```bash
103
+ # stdio transport (default — what desktop agents launch)
104
+ python -m graphify.serve graphify-out/graph.json
105
+ # or the console script after `pip install -e .`
106
+ graphify-mcp graphify-out/graph.json
107
+ # shared HTTP transport (team / remote)
108
+ python -m graphify.serve graphify-out/graph.json --transport http --port 8080
109
+ ```
110
+
111
+ **Claude Code** — one command (use an absolute path to `graph.json`):
112
+
113
+ ```bash
114
+ claude mcp add graphify-sf -- python -m graphify.serve /abs/path/to/graphify-out/graph.json
115
+ ```
116
+
117
+ **Claude Desktop / Cursor / Windsurf** — add to the MCP config
118
+ (`claude_desktop_config.json`, `.cursor/mcp.json`, …); they share this shape:
119
+
120
+ ```json
121
+ {
122
+ "mcpServers": {
123
+ "graphify-sf": {
124
+ "command": "python",
125
+ "args": ["-m", "graphify.serve", "/abs/path/to/graphify-out/graph.json"]
126
+ }
127
+ }
128
+ }
129
+ ```
130
+
131
+ **VS Code / GitHub Copilot** — `.vscode/mcp.json` uses the `servers` key:
132
+
133
+ ```json
134
+ {
135
+ "servers": {
136
+ "graphify-sf": {
137
+ "type": "stdio",
138
+ "command": "python",
139
+ "args": ["-m", "graphify.serve", "/abs/path/to/graphify-out/graph.json"]
140
+ }
141
+ }
142
+ }
143
+ ```
144
+
145
+ Then just ask, e.g. *"What breaks if I change `Opportunity.Amount`? Use graphify-sf."*
146
+
147
+ ### Option B — no MCP (CLI the agent shells out to)
148
+
149
+ For agents that run shell commands but have no MCP, point them at the CLI — each
150
+ command prints a token-bounded answer to stdout:
151
+
152
+ ```bash
153
+ python -m graphify.salesforce impact <node-id> --direction downstream
154
+ python -m graphify.salesforce violations --severity HIGH
155
+ python -m graphify.salesforce cpq-chain SBQQ__Quote__c
156
+ python -m graphify.salesforce ooe Opportunity
157
+ ```
158
+
159
+ ### Tell the agent to use it on every task
160
+
161
+ Drop a short rule into the agent's project-instructions file — `CLAUDE.md` (Claude
162
+ Code), `.github/copilot-instructions.md` (Copilot), `.cursorrules` (Cursor), or
163
+ `AGENTS.md`:
164
+
165
+ ```markdown
166
+ ## Salesforce knowledge graph
167
+ Before answering Salesforce impact / CPQ / Order-of-Execution / Governor-Limit
168
+ questions, consult the graphify-sf graph instead of reading raw metadata:
169
+ - If the `graphify-sf` MCP server is connected, call `sf_impact` / `sf_violations` /
170
+ `sf_cpq_chain` / `sf_ooe`.
171
+ - Otherwise run `python -m graphify.salesforce <impact|violations|cpq-chain|ooe> …`.
172
+ Rebuild it with `python -m graphify.salesforce extract <repo> --cpq-data <dir>`
173
+ after pulling fresh metadata.
174
+ ```
175
+
176
+ ## Coverage
177
+
178
+ | Area | Module | Status |
179
+ |---|---|---|
180
+ | Core parsers (Apex/Flow/LWC/Objects/Profiles) | `apex_enhanced`, `flow`, `lwc`, `objects`, `profiles` | ✅ |
181
+ | Metadata coverage (RecordType/PSG/Workflow/Custom Metadata/Sharing/Label/Setting) | `metadata`, `objects` | ✅ |
182
+ | CPQ rule data (SFDX + Gearset + JS QCP) | `cpq_data` | ✅ |
183
+ | `__mdt` field mapping (Opp→Quote) | `mdt_mapping` | ✅ |
184
+ | Token-minimized consumption (cluster/query/CLI/viz/MCP) | `pipeline`, `query`, `cli`, `viz` | ✅ |
185
+ | Neo4j export | `neo4j_sf` | ✅ |
186
+ | Apex cross-class call resolution | tree-sitter promotion | ⏸ deferred (ADR-019) |
187
+
188
+ ---
189
+
190
+ ## Inspiration & Credits
191
+
192
+ This project stands on the shoulders of [**graphify**](https://github.com/safishamsi/graphify)
193
+ by **[Safi Shamsi](https://github.com/safishamsi)**. The core idea, architecture, and
194
+ API ergonomics are theirs — `graphify-sf` is an independent, Salesforce-tailored
195
+ adaptation built with deep respect for the original work. If you need a
196
+ platform-agnostic solution, please use and support the upstream project.
197
+
198
+ > 본 프로젝트는 [graphify](https://github.com/safishamsi/graphify)의 아이디어와 아키텍처에서
199
+ > 출발했습니다. 핵심 개념에 대한 모든 공로는 원작자에게 있으며, `graphify-sf`는 이를 Salesforce
200
+ > 플랫폼(Apex/Flow/LWC/CPQ) 환경에 맞게 재구현한 독립적인 파생 프로젝트입니다. 원작자의 노고에
201
+ > 깊이 감사드립니다. 범용 환경이 필요하다면 원본 프로젝트를 사용하시길 권장합니다.
202
+
203
+ > The upstream project's original README is preserved in this repo as [`README.upstream.md`](./README.upstream.md).
204
+
205
+ ## License
206
+
207
+ MIT © Safi Shamsi (graphify) · MIT © JeremyKo95 (graphify-sf). See [LICENSE](./LICENSE).
@@ -0,0 +1,28 @@
1
+ """graphify - extract · build · cluster · analyze · report."""
2
+
3
+
4
+ def __getattr__(name):
5
+ # Lazy imports so `graphify install` works before heavy deps are in place.
6
+ _map = {
7
+ "extract": ("graphify.extract", "extract"),
8
+ "collect_files": ("graphify.extract", "collect_files"),
9
+ "build_from_json": ("graphify.build", "build_from_json"),
10
+ "cluster": ("graphify.cluster", "cluster"),
11
+ "score_all": ("graphify.cluster", "score_all"),
12
+ "cohesion_score": ("graphify.cluster", "cohesion_score"),
13
+ "god_nodes": ("graphify.analyze", "god_nodes"),
14
+ "surprising_connections": ("graphify.analyze", "surprising_connections"),
15
+ "suggest_questions": ("graphify.analyze", "suggest_questions"),
16
+ "generate": ("graphify.report", "generate"),
17
+ "to_json": ("graphify.export", "to_json"),
18
+ "to_html": ("graphify.export", "to_html"),
19
+ "to_svg": ("graphify.export", "to_svg"),
20
+ "to_canvas": ("graphify.export", "to_canvas"),
21
+ "to_wiki": ("graphify.wiki", "to_wiki"),
22
+ }
23
+ if name in _map:
24
+ import importlib
25
+ mod_name, attr = _map[name]
26
+ mod = importlib.import_module(mod_name)
27
+ return getattr(mod, attr)
28
+ raise AttributeError(f"module 'graphify' has no attribute {name!r}")