graphifyy 0.9.76__tar.gz → 0.9.77__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 (576) hide show
  1. {graphifyy-0.9.76/graphifyy.egg-info → graphifyy-0.9.77}/PKG-INFO +14 -1
  2. {graphifyy-0.9.76 → graphifyy-0.9.77}/README.md +13 -0
  3. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/build.py +8 -2
  4. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cli.py +8 -0
  5. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/detect.py +49 -13
  6. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/export.py +2 -0
  7. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/exporters/graphdb.py +3 -3
  8. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extract.py +10 -4
  9. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/engine.py +123 -6
  10. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/objc.py +60 -0
  11. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/powershell.py +41 -1
  12. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/rust.py +4 -0
  13. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/solidity.py +7 -1
  14. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/sql.py +23 -0
  15. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/paths.py +21 -0
  16. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-agents.md +5 -1
  17. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-amp.md +5 -1
  18. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-claw.md +5 -1
  19. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-codex.md +5 -1
  20. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-copilot.md +5 -1
  21. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-droid.md +5 -1
  22. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-kilo.md +5 -1
  23. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-kiro.md +5 -1
  24. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-opencode.md +5 -1
  25. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-pi.md +5 -1
  26. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-trae.md +5 -1
  27. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-vscode.md +5 -1
  28. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-windows.md +5 -1
  29. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill.md +5 -1
  30. {graphifyy-0.9.76 → graphifyy-0.9.77/graphifyy.egg-info}/PKG-INFO +14 -1
  31. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphifyy.egg-info/SOURCES.txt +5 -0
  32. {graphifyy-0.9.76 → graphifyy-0.9.77}/pyproject.toml +1 -1
  33. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_astro_extraction.py +29 -0
  34. graphifyy-0.9.77/tests/test_build_located_semantic_identity.py +88 -0
  35. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cpp_nested_and_cli.py +15 -0
  36. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_member_calls.py +18 -0
  37. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_detect.py +61 -0
  38. graphifyy-0.9.77/tests/test_export_direction.py +191 -0
  39. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extract.py +101 -0
  40. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_kotlin_grammar.py +23 -0
  41. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_languages.py +99 -4
  42. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_merge_graphs_cli.py +28 -0
  43. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_multilang.py +51 -0
  44. graphifyy-0.9.77/tests/test_objc_enum_declarations.py +85 -0
  45. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_partial_extraction_warning.py +19 -0
  46. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pascal.py +34 -0
  47. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_php_language_construct_calls.py +97 -0
  48. graphifyy-0.9.77/tests/test_rust_anonymous_const.py +24 -0
  49. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scala_context_bounds.py +91 -0
  50. graphifyy-0.9.77/tests/test_skill_semantic_all_cached.py +92 -0
  51. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_solidity_extractor.py +34 -0
  52. {graphifyy-0.9.76 → graphifyy-0.9.77}/LICENSE +0 -0
  53. {graphifyy-0.9.76 → graphifyy-0.9.77}/LICENSE-MIT +0 -0
  54. {graphifyy-0.9.76 → graphifyy-0.9.77}/NOTICE +0 -0
  55. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/__init__.py +0 -0
  56. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/__main__.py +0 -0
  57. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/_minhash.py +0 -0
  58. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/affected.py +0 -0
  59. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/agents-md.md +0 -0
  60. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/antigravity-rules.md +0 -0
  61. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/claude-md.md +0 -0
  62. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/gemini-md.md +0 -0
  63. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/kiro-steering.md +0 -0
  64. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/always_on/vscode-instructions.md +0 -0
  65. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/analyze.py +0 -0
  66. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/benchmark.py +0 -0
  67. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cache.py +0 -0
  68. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/callflow_html.py +0 -0
  69. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cargo_introspect.py +0 -0
  70. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cluster.py +0 -0
  71. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/command-kilo.md +0 -0
  72. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cross_repo_calls.py +0 -0
  73. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/cross_repo_types.py +0 -0
  74. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/csharp_dispatch.py +0 -0
  75. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/dedup.py +0 -0
  76. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/diagnostics.py +0 -0
  77. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/exporters/__init__.py +0 -0
  78. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/exporters/base.py +0 -0
  79. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/exporters/html.py +0 -0
  80. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/__init__.py +0 -0
  81. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/apex.py +0 -0
  82. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/base.py +0 -0
  83. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/bash.py +0 -0
  84. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/blade.py +0 -0
  85. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/cobol.py +0 -0
  86. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/commonlisp.py +0 -0
  87. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/csharp.py +0 -0
  88. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/dart.py +0 -0
  89. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/dm.py +0 -0
  90. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/elixir.py +0 -0
  91. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/erlang.py +0 -0
  92. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/fortran.py +0 -0
  93. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/go.py +0 -0
  94. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/json_config.py +0 -0
  95. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/julia.py +0 -0
  96. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/markdown.py +0 -0
  97. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/models.py +0 -0
  98. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/ocaml.py +0 -0
  99. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/pascal.py +0 -0
  100. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/pascal_forms.py +0 -0
  101. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/r.py +0 -0
  102. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/razor.py +0 -0
  103. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/resolution.py +0 -0
  104. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/robot.py +0 -0
  105. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/sln.py +0 -0
  106. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/terraform.py +0 -0
  107. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/vbnet.py +0 -0
  108. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/verilog.py +0 -0
  109. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/extractors/zig.py +0 -0
  110. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/file_slice.py +0 -0
  111. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/global_graph.py +0 -0
  112. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/google_workspace.py +0 -0
  113. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/hooks.py +0 -0
  114. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/ids.py +0 -0
  115. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/ingest.py +0 -0
  116. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/install.py +0 -0
  117. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/interface_dispatch.py +0 -0
  118. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/llm.py +0 -0
  119. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/manifest.py +0 -0
  120. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/manifest_ingest.py +0 -0
  121. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/markdown_resolution.py +0 -0
  122. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/mcp_ingest.py +0 -0
  123. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/multigraph_compat.py +0 -0
  124. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/pascal_resolution.py +0 -0
  125. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/pg_introspect.py +0 -0
  126. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/prs.py +0 -0
  127. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/querylog.py +0 -0
  128. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/reflect.py +0 -0
  129. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/report.py +0 -0
  130. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/resolver_registry.py +0 -0
  131. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/ruby_resolution.py +0 -0
  132. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/scip_ingest.py +0 -0
  133. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/security.py +0 -0
  134. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/semantic_cleanup.py +0 -0
  135. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/serve.py +0 -0
  136. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-aider.md +0 -0
  137. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skill-devin.md +0 -0
  138. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/add-watch.md +0 -0
  139. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/exports.md +0 -0
  140. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/extraction-spec.md +0 -0
  141. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/github-and-merge.md +0 -0
  142. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/hooks.md +0 -0
  143. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/query.md +0 -0
  144. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/transcribe.md +0 -0
  145. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/agents/references/update.md +0 -0
  146. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/add-watch.md +0 -0
  147. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/exports.md +0 -0
  148. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/extraction-spec.md +0 -0
  149. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/github-and-merge.md +0 -0
  150. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/hooks.md +0 -0
  151. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/query.md +0 -0
  152. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/transcribe.md +0 -0
  153. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/amp/references/update.md +0 -0
  154. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/add-watch.md +0 -0
  155. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/exports.md +0 -0
  156. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/extraction-spec.md +0 -0
  157. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/github-and-merge.md +0 -0
  158. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/hooks.md +0 -0
  159. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/query.md +0 -0
  160. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/transcribe.md +0 -0
  161. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claude/references/update.md +0 -0
  162. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/add-watch.md +0 -0
  163. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/exports.md +0 -0
  164. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/extraction-spec.md +0 -0
  165. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/github-and-merge.md +0 -0
  166. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/hooks.md +0 -0
  167. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/query.md +0 -0
  168. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/transcribe.md +0 -0
  169. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/claw/references/update.md +0 -0
  170. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/add-watch.md +0 -0
  171. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/exports.md +0 -0
  172. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/extraction-spec.md +0 -0
  173. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/github-and-merge.md +0 -0
  174. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/hooks.md +0 -0
  175. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/query.md +0 -0
  176. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/transcribe.md +0 -0
  177. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/codex/references/update.md +0 -0
  178. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/add-watch.md +0 -0
  179. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/exports.md +0 -0
  180. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/extraction-spec.md +0 -0
  181. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/github-and-merge.md +0 -0
  182. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/hooks.md +0 -0
  183. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/query.md +0 -0
  184. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/transcribe.md +0 -0
  185. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/copilot/references/update.md +0 -0
  186. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/add-watch.md +0 -0
  187. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/exports.md +0 -0
  188. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/extraction-spec.md +0 -0
  189. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/github-and-merge.md +0 -0
  190. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/hooks.md +0 -0
  191. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/query.md +0 -0
  192. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/transcribe.md +0 -0
  193. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/droid/references/update.md +0 -0
  194. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/add-watch.md +0 -0
  195. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/exports.md +0 -0
  196. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/extraction-spec.md +0 -0
  197. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/github-and-merge.md +0 -0
  198. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/hooks.md +0 -0
  199. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/query.md +0 -0
  200. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/transcribe.md +0 -0
  201. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kilo/references/update.md +0 -0
  202. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/add-watch.md +0 -0
  203. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/exports.md +0 -0
  204. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/extraction-spec.md +0 -0
  205. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/github-and-merge.md +0 -0
  206. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/hooks.md +0 -0
  207. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/query.md +0 -0
  208. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/transcribe.md +0 -0
  209. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/kiro/references/update.md +0 -0
  210. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/add-watch.md +0 -0
  211. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/exports.md +0 -0
  212. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/extraction-spec.md +0 -0
  213. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/github-and-merge.md +0 -0
  214. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/hooks.md +0 -0
  215. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/query.md +0 -0
  216. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/transcribe.md +0 -0
  217. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/opencode/references/update.md +0 -0
  218. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/add-watch.md +0 -0
  219. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/exports.md +0 -0
  220. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/extraction-spec.md +0 -0
  221. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/github-and-merge.md +0 -0
  222. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/hooks.md +0 -0
  223. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/query.md +0 -0
  224. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/transcribe.md +0 -0
  225. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/pi/references/update.md +0 -0
  226. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/add-watch.md +0 -0
  227. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/exports.md +0 -0
  228. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/extraction-spec.md +0 -0
  229. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/github-and-merge.md +0 -0
  230. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/hooks.md +0 -0
  231. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/query.md +0 -0
  232. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/transcribe.md +0 -0
  233. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/trae/references/update.md +0 -0
  234. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/add-watch.md +0 -0
  235. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/exports.md +0 -0
  236. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/extraction-spec.md +0 -0
  237. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/github-and-merge.md +0 -0
  238. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/hooks.md +0 -0
  239. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/query.md +0 -0
  240. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/transcribe.md +0 -0
  241. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/vscode/references/update.md +0 -0
  242. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/add-watch.md +0 -0
  243. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/exports.md +0 -0
  244. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/extraction-spec.md +0 -0
  245. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/github-and-merge.md +0 -0
  246. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/hooks.md +0 -0
  247. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/query.md +0 -0
  248. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/transcribe.md +0 -0
  249. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/skills/windows/references/update.md +0 -0
  250. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/swift_dispatch.py +0 -0
  251. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/symbol_resolution.py +0 -0
  252. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/transcribe.py +0 -0
  253. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/tree_html.py +0 -0
  254. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/validate.py +0 -0
  255. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/watch.py +0 -0
  256. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphify/wiki.py +0 -0
  257. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphifyy.egg-info/dependency_links.txt +0 -0
  258. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphifyy.egg-info/entry_points.txt +0 -0
  259. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphifyy.egg-info/requires.txt +0 -0
  260. {graphifyy-0.9.76 → graphifyy-0.9.77}/graphifyy.egg-info/top_level.txt +0 -0
  261. {graphifyy-0.9.76 → graphifyy-0.9.77}/setup.cfg +0 -0
  262. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_affected_cli.py +0 -0
  263. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_affected_member_seed.py +0 -0
  264. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_agents_platform.py +0 -0
  265. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_analyze.py +0 -0
  266. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_anthropic_custom_endpoint.py +0 -0
  267. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_antigravity_install.py +0 -0
  268. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_apm_fallback_version.py +0 -0
  269. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_architecture_doc.py +0 -0
  270. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_astro_import_ids.py +0 -0
  271. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_atomic_canvas_export.py +0 -0
  272. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_atomic_version_stamp.py +0 -0
  273. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_atomic_writes.py +0 -0
  274. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_backend_env_isolation.py +0 -0
  275. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_backend_extras.py +0 -0
  276. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_benchmark.py +0 -0
  277. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_benchmark_raw_graph.py +0 -0
  278. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_blade_extractor.py +0 -0
  279. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_build.py +0 -0
  280. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_build_merge_dedup_scope.py +0 -0
  281. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_build_merge_hyperedges_and_prune.py +0 -0
  282. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_build_merge_shrink_guard.py +0 -0
  283. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_builtin_global_type_refs.py +0 -0
  284. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cache.py +0 -0
  285. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_callflow_html.py +0 -0
  286. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cargo_introspect.py +0 -0
  287. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cargo_missing_manifest.py +0 -0
  288. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_carried_hyperedge_remap.py +0 -0
  289. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_case_sensitive_resolution.py +0 -0
  290. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_charmap_encoding.py +0 -0
  291. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_chunking.py +0 -0
  292. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cjs_module_extension.py +0 -0
  293. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_claude_cli_backend.py +0 -0
  294. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_claude_md.py +0 -0
  295. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cli_broken_pipe.py +0 -0
  296. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cli_export.py +0 -0
  297. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cli_help.py +0 -0
  298. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cluster.py +0 -0
  299. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cluster_exclude_hubs.py +0 -0
  300. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cobol_extractor.py +0 -0
  301. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_codebuddy.py +0 -0
  302. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_community_hub_labels.py +0 -0
  303. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_community_labels_skill.py +0 -0
  304. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_confidence.py +0 -0
  305. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_corrupt_graph_json.py +0 -0
  306. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cpp_method_declarations.py +0 -0
  307. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cpp_objc_cross_file_calls.py +0 -0
  308. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cpp_preprocess.py +0 -0
  309. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cross_extension_reexport_self_cycle.py +0 -0
  310. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cross_language_call_resolution.py +0 -0
  311. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cross_repo_external_call_guards.py +0 -0
  312. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cross_repo_member_calls.py +0 -0
  313. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_cross_repo_shared_types.py +0 -0
  314. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_call_site_generic_args.py +0 -0
  315. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_enum_members.py +0 -0
  316. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_field_generic_args.py +0 -0
  317. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_generic_callsites.py +0 -0
  318. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_interface_dispatch.py +0 -0
  319. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_member_nodes.py +0 -0
  320. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_object_creation.py +0 -0
  321. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_partial_classes.py +0 -0
  322. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_tuple_type_refs.py +0 -0
  323. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_csharp_type_resolution.py +0 -0
  324. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dart.py +0 -0
  325. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dedup.py +0 -0
  326. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dedup_remaps_hyperedges.py +0 -0
  327. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dedup_shrink_refuses_force_write.py +0 -0
  328. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dedup_survivor_richness.py +0 -0
  329. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_definition_file_portability.py +0 -0
  330. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_devin.py +0 -0
  331. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_docx_to_markdown.py +0 -0
  332. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_dotnet.py +0 -0
  333. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_duplicate_annotation_edges.py +0 -0
  334. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_elixir_import_resolution.py +0 -0
  335. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_elixir_unqualified_call_scope.py +0 -0
  336. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_erlang_extractor.py +0 -0
  337. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_evidence_binding.py +0 -0
  338. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_explain_cli.py +0 -0
  339. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_export.py +0 -0
  340. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_export_control_characters.py +0 -0
  341. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_export_idempotent_writes.py +0 -0
  342. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_export_path_length.py +0 -0
  343. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_external_stub_endpoints.py +0 -0
  344. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extract_cache_location.py +0 -0
  345. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extract_cli.py +0 -0
  346. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extract_code_only_cli.py +0 -0
  347. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extract_php_closures.py +0 -0
  348. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extraction_spec_ids.py +0 -0
  349. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_extractors_registry.py +0 -0
  350. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_falkordb_integration.py +0 -0
  351. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_file_label_disambiguation.py +0 -0
  352. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_file_node_id_spec.py +0 -0
  353. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_file_slice.py +0 -0
  354. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_file_truncation_warning.py +0 -0
  355. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_forwarding_review_findings.py +0 -0
  356. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_gemini_hook.py +0 -0
  357. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_global_add_tag_inference.py +0 -0
  358. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_global_graph.py +0 -0
  359. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_go_builtin_call_targets.py +0 -0
  360. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_go_import_repoint.py +0 -0
  361. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_go_interface_methods.py +0 -0
  362. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_go_qualified_resolution.py +0 -0
  363. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_god_nodes_cli.py +0 -0
  364. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_god_nodes_exclude_hubs.py +0 -0
  365. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_google_workspace.py +0 -0
  366. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_graphdb_push_indexes.py +0 -0
  367. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hollow_chunks_arm_shrink_guard.py +0 -0
  368. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_home_sandbox.py +0 -0
  369. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hook_chain_survives_skip.py +0 -0
  370. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hook_guard.py +0 -0
  371. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hook_guard_token_match.py +0 -0
  372. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hook_out_of_project_paths.py +0 -0
  373. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hook_strict.py +0 -0
  374. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hooks.py +0 -0
  375. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hyperedge_member_shapes.py +0 -0
  376. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hyperedge_roundtrip.py +0 -0
  377. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_hypergraph.py +0 -0
  378. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_id_normalization_contract.py +0 -0
  379. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ignore_file_encoding.py +0 -0
  380. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_image_vision.py +0 -0
  381. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_import_extension_resolution.py +0 -0
  382. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_import_self_loops.py +0 -0
  383. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_imported_export_forwarding.py +0 -0
  384. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_incomplete_build_guard.py +0 -0
  385. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_incremental.py +0 -0
  386. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_incremental_mtime_collision.py +0 -0
  387. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_arrow_single_param_shadow.py +0 -0
  388. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_block_scoped_shadow.py +0 -0
  389. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_catch_binding_shadow.py +0 -0
  390. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_external_import_shadow.py +0 -0
  391. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_for_of_binding_shadow.py +0 -0
  392. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_function_expression_shadow.py +0 -0
  393. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_call_nested_closure_shadow.py +0 -0
  394. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_dispatch.py +0 -0
  395. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_dispatch_assign_return.py +0 -0
  396. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_indirect_dispatch_getattr.py +0 -0
  397. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_inferred_confidence_rubric.py +0 -0
  398. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ingest.py +0 -0
  399. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ingest_url_type.py +0 -0
  400. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_inherited_field_receivers.py +0 -0
  401. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_injection_sentinel_coverage.py +0 -0
  402. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install.py +0 -0
  403. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_references.py +0 -0
  404. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_roundtrip.py +0 -0
  405. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_strings.py +0 -0
  406. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_upgrade.py +0 -0
  407. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_version_stamp.py +0 -0
  408. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_install_version_warning.py +0 -0
  409. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_issue_3405_python_resolution.py +0 -0
  410. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_issue_3472_source_file_collision.py +0 -0
  411. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_java_enum_members.py +0 -0
  412. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_java_member_calls.py +0 -0
  413. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_java_type_resolution.py +0 -0
  414. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_callback_calls.py +0 -0
  415. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_destructured_export.py +0 -0
  416. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_dynamic_import_affected.py +0 -0
  417. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_dynamic_imports.py +0 -0
  418. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_exported_fn_call_resolution.py +0 -0
  419. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_exported_scalar_bindings.py +0 -0
  420. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_import_resolution.py +0 -0
  421. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_module_level_anonymous_calls.py +0 -0
  422. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_js_this_member_expressions.py +0 -0
  423. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_jsconfig_baseurl.py +0 -0
  424. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_json_schema_config.py +0 -0
  425. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_jsx_component_usage_calls.py +0 -0
  426. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_kotlin_object_literal.py +0 -0
  427. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_label_retry.py +0 -0
  428. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_labeling.py +0 -0
  429. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_language_resolvers.py +0 -0
  430. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_llm_backends.py +0 -0
  431. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_llm_parser.py +0 -0
  432. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_llm_parser_reasoning.py +0 -0
  433. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_long_path_hashing.py +0 -0
  434. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_loose_sibling_import_resolution.py +0 -0
  435. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_lua_import.py +0 -0
  436. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_lua_method_calls.py +0 -0
  437. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_manifest_ingest.py +0 -0
  438. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_manifest_tomli_required.py +0 -0
  439. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_markdown_code_spans.py +0 -0
  440. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_mcp_ingest.py +0 -0
  441. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_merge_chunks_validation.py +0 -0
  442. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_minhash.py +0 -0
  443. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_multigraph_compat.py +0 -0
  444. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_multigraph_diagnostics.py +0 -0
  445. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_no_dedup_flag.py +0 -0
  446. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_node_id_canonical.py +0 -0
  447. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_non_regular_files.py +0 -0
  448. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_non_string_node_ids.py +0 -0
  449. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_objc_category_interfaces.py +0 -0
  450. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_objc_field_table_remap.py +0 -0
  451. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_objc_member_calls.py +0 -0
  452. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_objc_property_ivar_receivers.py +0 -0
  453. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_obsidian_dangling_member.py +0 -0
  454. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_obsidian_filename_cap.py +0 -0
  455. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_obsidian_unicode_tags.py +0 -0
  456. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_obsidian_vault_migration.py +0 -0
  457. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ocaml.py +0 -0
  458. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_office_incremental.py +0 -0
  459. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_office_limits.py +0 -0
  460. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ollama.py +0 -0
  461. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ollama_retry_cap.py +0 -0
  462. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_openai_custom_endpoint.py +0 -0
  463. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_out_dir_evidence.py +0 -0
  464. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_oversized_document_slicing.py +0 -0
  465. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_owned_type_sources.py +0 -0
  466. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_package_json_subpath_imports.py +0 -0
  467. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_partial_cache.py +0 -0
  468. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pascal_call_scoping.py +0 -0
  469. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pascal_resolution.py +0 -0
  470. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_path_cli.py +0 -0
  471. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_paths.py +0 -0
  472. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pdf_extra_warning.py +0 -0
  473. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pdf_slicing.py +0 -0
  474. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pdf_token_estimate.py +0 -0
  475. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pg_introspect.py +0 -0
  476. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_phantom_cross_package_call.py +0 -0
  477. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_phantom_external_import.py +0 -0
  478. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_php_object_creation.py +0 -0
  479. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_php_type_resolution.py +0 -0
  480. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pin_hash_seed.py +0 -0
  481. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_pipeline.py +0 -0
  482. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_provider_registry.py +0 -0
  483. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_prs.py +0 -0
  484. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_prune_sweeps_orphans.py +0 -0
  485. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_python_decorators.py +0 -0
  486. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_python_import_resolution.py +0 -0
  487. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_python_parse_memoization.py +0 -0
  488. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_python_underscore_resolution.py +0 -0
  489. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_query_cli.py +0 -0
  490. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_query_induced_edges.py +0 -0
  491. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_query_mcp_direction.py +0 -0
  492. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_query_names_its_graph.py +0 -0
  493. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_querylog.py +0 -0
  494. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_r_extractor.py +0 -0
  495. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_rationale.py +0 -0
  496. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_read_hook.py +0 -0
  497. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_reflect.py +0 -0
  498. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_relation_collapse_precedence.py +0 -0
  499. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_replace_or_append_section.py +0 -0
  500. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_report.py +0 -0
  501. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_report_gap_thresholds.py +0 -0
  502. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_resolve_memoization.py +0 -0
  503. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ruby_bare_self_send_calls.py +0 -0
  504. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ruby_resolution.py +0 -0
  505. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_rust_builtin_type_hubs.py +0 -0
  506. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_rust_macro_rules.py +0 -0
  507. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_rust_self_member_calls.py +0 -0
  508. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scala_abstract_methods.py +0 -0
  509. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scala_self_type.py +0 -0
  510. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scala_top_level_binding.py +0 -0
  511. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scala_type_definition.py +0 -0
  512. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_scip_ingest.py +0 -0
  513. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_search_hook.py +0 -0
  514. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_security.py +0 -0
  515. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_cache_basename_recovery.py +0 -0
  516. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_cache_out_root.py +0 -0
  517. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_cleanup.py +0 -0
  518. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_fragment_sanitize.py +0 -0
  519. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_id_remap_root.py +0 -0
  520. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_semantic_similarity.py +0 -0
  521. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_serve.py +0 -0
  522. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_serve_http.py +0 -0
  523. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_settings_merge.py +0 -0
  524. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_skill_auto_refresh.py +0 -0
  525. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_skill_version_warning.py +0 -0
  526. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_skillgen.py +0 -0
  527. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_skillgen_input_path_injection.py +0 -0
  528. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_source_key_memoization.py +0 -0
  529. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_sourceless_call_targets.py +0 -0
  530. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_src_layout_import_resolution.py +0 -0
  531. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_stale_prune.py +0 -0
  532. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_stat_index_husk.py +0 -0
  533. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_stat_index_multi_root.py +0 -0
  534. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_stat_index_portability.py +0 -0
  535. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_svelte_extraction.py +0 -0
  536. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_builtin_noise.py +0 -0
  537. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_computed_properties.py +0 -0
  538. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_cross_file_calls.py +0 -0
  539. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_import_resolution.py +0 -0
  540. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_protocol_dispatch.py +0 -0
  541. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_swift_protocol_requirements.py +0 -0
  542. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_symbol_resolution.py +0 -0
  543. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_terraform.py +0 -0
  544. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_terraform_modules.py +0 -0
  545. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_trailing_newline_not_a_syntax_error.py +0 -0
  546. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_transcribe.py +0 -0
  547. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_tree_html.py +0 -0
  548. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_abstract_methods.py +0 -0
  549. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_decorators.py +0 -0
  550. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_generators.py +0 -0
  551. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_import_require.py +0 -0
  552. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_import_type_arguments.py +0 -0
  553. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_inheritance.py +0 -0
  554. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_namespace.py +0 -0
  555. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_new_expression_calls.py +0 -0
  556. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_parse_warning.py +0 -0
  557. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_ts_receiver_member_calls.py +0 -0
  558. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_type_only_import_cycles.py +0 -0
  559. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_typescript_enum_members.py +0 -0
  560. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_typescript_module_extensions.py +0 -0
  561. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_uninstall_scope.py +0 -0
  562. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_uninstall_symlink.py +0 -0
  563. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_unmapped_at_alias_resolution.py +0 -0
  564. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_unverified_semantic_shrink.py +0 -0
  565. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_validate.py +0 -0
  566. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_vbnet_extractor.py +0 -0
  567. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_vue_extraction.py +0 -0
  568. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_walk_python_tree_iterative.py +0 -0
  569. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_watch.py +0 -0
  570. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_watch_manifest_location.py +0 -0
  571. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_wheel_packaging.py +0 -0
  572. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_wiki.py +0 -0
  573. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_wiki_link_filename_parity.py +0 -0
  574. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_wiki_truncation_indicator.py +0 -0
  575. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_word_count_cache.py +0 -0
  576. {graphifyy-0.9.76 → graphifyy-0.9.77}/tests/test_zero_node_no_cache.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphifyy
3
- Version: 0.9.76
3
+ Version: 0.9.77
4
4
  Summary: AI coding assistant skill (Claude Code, CodeBuddy, Codex, OpenCode, Kilo Code, Cursor, Gemini CLI, Aider, OpenClaw, Factory Droid, Trae, Hermes, Kiro, Pi, Devin CLI, Google Antigravity) - turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Homepage, https://graphify.com
@@ -277,6 +277,7 @@ What you get out of the box:
277
277
  | LOCOMO (n=300) | recall@10 | **0.497** | mem0 0.048, supermemory 0.149 |
278
278
  | LOCOMO (n=300) | QA accuracy | 45.3% | supermemory 49.7%, mem0 27.3% |
279
279
  | LongMemEval-S (n=50) | QA accuracy | **76%** | tied with dense RAG |
280
+ | ERPNext cross-tool (n=6) | key-fact coverage | **82.0%** | grep/read baseline 70.8% |
280
281
  | Graph build | LLM credits | **0** | per-token for most systems |
281
282
 
282
283
  Every system ran on the same harness with the same model and budgets, scored by a judge blind-validated against a second judge (90.6% agreement, Cohen's kappa 0.81). Full per-system tables, the code-intelligence result, and reproduction commands: **[BENCHMARKS.md](./BENCHMARKS.md)**.
@@ -1011,6 +1012,12 @@ graphify label ./my-project # (re)name commun
1011
1012
  graphify label ./my-project --backend=openai --model gpt-4o # force a specific backend and model
1012
1013
  ```
1013
1014
 
1015
+ `--no-dedup` also skips coalescing distinct non-AST nodes solely because they
1016
+ share a file and label. The Python equivalents are `build(chunks, dedup=False)`,
1017
+ `build_merge(chunks, graph_path, dedup=False)`, and
1018
+ `build_from_json(extraction, dedup=False)`. AST/semantic twins still reconcile to
1019
+ the canonical AST node, and document-file twin reconciliation remains enabled.
1020
+
1014
1021
  > **Community names:** inside an agent (Claude Code, Gemini CLI) the agent names communities itself. When you run the bare CLI, `cluster-only` auto-names them with the configured backend (built-in or custom OpenAI-compatible provider) — pass `--no-label` to keep `Community N`, or run `graphify label` to (re)generate names on demand.
1015
1022
 
1016
1023
  ---
@@ -1053,6 +1060,12 @@ Made with [contrib.rocks](https://contrib.rocks).
1053
1060
 
1054
1061
  ---
1055
1062
 
1063
+ ## Translations
1064
+
1065
+ The README is available in 32 languages. Use the language switcher at the top of this file to read it in yours, or browse [`docs/translations/`](docs/translations/). To improve a translation or add a new one, open a pull request against the matching file there.
1066
+
1067
+ ---
1068
+
1056
1069
  ## Community and links
1057
1070
 
1058
1071
  <p align="center">
@@ -126,6 +126,7 @@ What you get out of the box:
126
126
  | LOCOMO (n=300) | recall@10 | **0.497** | mem0 0.048, supermemory 0.149 |
127
127
  | LOCOMO (n=300) | QA accuracy | 45.3% | supermemory 49.7%, mem0 27.3% |
128
128
  | LongMemEval-S (n=50) | QA accuracy | **76%** | tied with dense RAG |
129
+ | ERPNext cross-tool (n=6) | key-fact coverage | **82.0%** | grep/read baseline 70.8% |
129
130
  | Graph build | LLM credits | **0** | per-token for most systems |
130
131
 
131
132
  Every system ran on the same harness with the same model and budgets, scored by a judge blind-validated against a second judge (90.6% agreement, Cohen's kappa 0.81). Full per-system tables, the code-intelligence result, and reproduction commands: **[BENCHMARKS.md](./BENCHMARKS.md)**.
@@ -860,6 +861,12 @@ graphify label ./my-project # (re)name commun
860
861
  graphify label ./my-project --backend=openai --model gpt-4o # force a specific backend and model
861
862
  ```
862
863
 
864
+ `--no-dedup` also skips coalescing distinct non-AST nodes solely because they
865
+ share a file and label. The Python equivalents are `build(chunks, dedup=False)`,
866
+ `build_merge(chunks, graph_path, dedup=False)`, and
867
+ `build_from_json(extraction, dedup=False)`. AST/semantic twins still reconcile to
868
+ the canonical AST node, and document-file twin reconciliation remains enabled.
869
+
863
870
  > **Community names:** inside an agent (Claude Code, Gemini CLI) the agent names communities itself. When you run the bare CLI, `cluster-only` auto-names them with the configured backend (built-in or custom OpenAI-compatible provider) — pass `--no-label` to keep `Community N`, or run `graphify label` to (re)generate names on demand.
864
871
 
865
872
  ---
@@ -902,6 +909,12 @@ Made with [contrib.rocks](https://contrib.rocks).
902
909
 
903
910
  ---
904
911
 
912
+ ## Translations
913
+
914
+ The README is available in 32 languages. Use the language switcher at the top of this file to read it in yours, or browse [`docs/translations/`](docs/translations/). To improve a translation or add a new one, open a pull request against the matching file there.
915
+
916
+ ---
917
+
905
918
  ## Community and links
906
919
 
907
920
  <p align="center">
@@ -874,13 +874,17 @@ def _doc_twin_remap(nodes: list) -> dict[str, str]:
874
874
  return remap
875
875
 
876
876
 
877
- def build_from_json(extraction: dict, *, directed: bool = False, root: str | Path | None = None) -> nx.Graph:
877
+ def build_from_json(extraction: dict, *, directed: bool = False, root: str | Path | None = None,
878
+ dedup: bool = True) -> nx.Graph:
878
879
  """Build a NetworkX graph from an extraction dict.
879
880
 
880
881
  directed=True produces a DiGraph that preserves edge direction (source→target).
881
882
  directed=False (default) produces an undirected Graph for backward compatibility.
882
883
  root: if given, absolute source_file paths from semantic subagents are made
883
884
  relative to root so all nodes share a consistent path key (#932).
885
+ dedup=False preserves distinct non-AST IDs rather than coalescing nodes by
886
+ file and label. AST/semantic and document-file twin reconciliation
887
+ remain enabled.
884
888
  """
885
889
  _root = str(Path(root).resolve()) if root else None
886
890
  # NetworkX <= 3.1 serialised edges as "links"; remap to "edges" for compatibility.
@@ -1158,6 +1162,8 @@ def build_from_json(extraction: dict, *, directed: bool = False, root: str | Pat
1158
1162
  if key in _loc_collisions:
1159
1163
  continue # ambiguous key: no safe canonical winner, leave ghost intact
1160
1164
  if key in _loc_nodes and _loc_nodes[key] != nid:
1165
+ if not dedup and G.nodes[_loc_nodes[key]].get("_origin") != "ast":
1166
+ continue
1161
1167
  _noloc_nodes[key] = nid
1162
1168
  elif key not in _loc_nodes:
1163
1169
  # Spec-conformant method ghost omitting class segment / leading dot
@@ -1599,7 +1605,7 @@ def build(
1599
1605
  protected_ids=protected_ids,
1600
1606
  )
1601
1607
  _dedup_collapsed = _before_dedup - len(combined["nodes"])
1602
- G = build_from_json(combined, directed=directed, root=_root)
1608
+ G = build_from_json(combined, directed=directed, root=_root, dedup=dedup)
1603
1609
  # CLI reads this to tell a dedup shrink from a file deletion (#3774).
1604
1610
  # Popped before to_json so it is not stored in graph.json.
1605
1611
  if _dedup_collapsed:
@@ -2684,6 +2684,12 @@ def dispatch_command(cmd: str) -> None:
2684
2684
  out_data = _jg.node_link_data(merged, edges="links")
2685
2685
  except TypeError:
2686
2686
  out_data = _jg.node_link_data(merged)
2687
+ # Write direction back into arc order, as to_json does (#563): the
2688
+ # loader stamped _src/_tgt, and compose() kept them on each edge.
2689
+ for _link in out_data.get("links", []):
2690
+ _ts, _tt = _link.pop("_src", None), _link.pop("_tgt", None)
2691
+ if _ts is not None and _tt is not None:
2692
+ _link["source"], _link["target"] = _ts, _tt
2687
2693
  from graphify.paths import write_json_atomic
2688
2694
  write_json_atomic(_current_path, out_data, indent=2)
2689
2695
  sys.exit(0)
@@ -3081,6 +3087,8 @@ def dispatch_command(cmd: str) -> None:
3081
3087
  _raw = json.loads(graph_path.read_text(encoding="utf-8"))
3082
3088
  if "links" not in _raw and "edges" in _raw:
3083
3089
  _raw = dict(_raw, links=_raw["edges"])
3090
+ from graphify.paths import restore_arc_direction as _rad
3091
+ _raw = _rad(_raw)
3084
3092
  try:
3085
3093
  G = _jg.node_link_graph(_raw, edges="links")
3086
3094
  except TypeError:
@@ -22,7 +22,7 @@ from graphify.google_workspace import (
22
22
  convert_google_workspace_file,
23
23
  google_workspace_enabled,
24
24
  )
25
- from graphify.paths import GRAPHIFY_OUT, out_path
25
+ from graphify.paths import GRAPHIFY_OUT, GRAPHIFY_OUT_NAME, out_path
26
26
 
27
27
 
28
28
  class FileType(str, Enum):
@@ -2397,6 +2397,27 @@ def _collapse_manifest_duplicates(
2397
2397
  return result
2398
2398
 
2399
2399
 
2400
+ def _manifest_storage_anchor(manifest_path: str | Path | None, root: Path | None) -> Path | None:
2401
+ """When a manifest lives under <repo>/graphify-out/manifest.json and root
2402
+ is a subfolder of <repo>, stored relative keys are anchored to <repo> (#3785)."""
2403
+ if root is None or not manifest_path:
2404
+ return root
2405
+ try:
2406
+ mp = Path(manifest_path).resolve()
2407
+ if mp.parent.name in ("graphify-out", GRAPHIFY_OUT_NAME):
2408
+ manifest_base = mp.parent.parent
2409
+ root_resolved = Path(root).resolve()
2410
+ if root_resolved != manifest_base:
2411
+ try:
2412
+ root_resolved.relative_to(manifest_base)
2413
+ return manifest_base
2414
+ except ValueError:
2415
+ pass
2416
+ except (OSError, RuntimeError):
2417
+ pass
2418
+ return root
2419
+
2420
+
2400
2421
  def load_manifest(
2401
2422
  manifest_path: str = _MANIFEST_PATH,
2402
2423
  *,
@@ -2421,8 +2442,9 @@ def load_manifest(
2421
2442
  return raw
2422
2443
  if root is None:
2423
2444
  return _collapse_manifest_duplicates(raw.items(), _nfc)
2445
+ anchor = _manifest_storage_anchor(manifest_path, root) or root
2424
2446
  return _collapse_manifest_duplicates(
2425
- raw.items(), lambda k: _nfc(_to_absolute_from_storage(k, root))
2447
+ raw.items(), lambda k: _nfc(_to_absolute_from_storage(k, anchor))
2426
2448
  )
2427
2449
 
2428
2450
 
@@ -2624,18 +2646,10 @@ def save_manifest(
2624
2646
  "semantic_hash": sem_h,
2625
2647
  }
2626
2648
  manifest[key] = entry
2627
- if root is not None:
2628
- # Persist in portable form: forward-slash relative paths. Keys outside
2629
- # ``root`` (out-of-tree symlinked corpora, --include sources) keep
2630
- # their absolute form so the manifest round-trips on the saving
2631
- # machine even when not every entry can be portably encoded.
2632
- # NFC after relativize so on-disk keys match what load_manifest
2633
- # re-anchors and compares against (#2221). A seeded absolute key and
2634
- # a seeded relative key for the same file collapse here too (#1964)
2635
- # -- _collapse_manifest_duplicates keeps whichever is more recently
2636
- # seen instead of whichever the dict comprehension iterates last.
2649
+ storage_root = _manifest_storage_anchor(manifest_path, root) if root is not None else None
2650
+ if storage_root is not None:
2637
2651
  manifest = _collapse_manifest_duplicates(
2638
- manifest.items(), lambda k: _nfc(_to_relative_for_storage(k, root))
2652
+ manifest.items(), lambda k: _nfc(_to_relative_for_storage(k, storage_root))
2639
2653
  )
2640
2654
  else:
2641
2655
  manifest = _collapse_manifest_duplicates(manifest.items(), _nfc)
@@ -2813,10 +2827,32 @@ def detect_incremental(
2813
2827
  # current scan was EXCLUDED (ignore rules / --exclude changed) and must
2814
2828
  # not be reported as deleted. Mirrors the watch-side excluded-vs-deleted
2815
2829
  # distinction (#1795).
2830
+ try:
2831
+ root_res: Path | None = Path(root).resolve() if root is not None else None
2832
+ except (OSError, RuntimeError):
2833
+ root_res = Path(root) if root is not None else None
2834
+
2835
+ def _in_root(path_str: str) -> bool:
2836
+ if root_res is None:
2837
+ return True
2838
+ p = Path(path_str)
2839
+ try:
2840
+ p.relative_to(root_res)
2841
+ return True
2842
+ except ValueError:
2843
+ pass
2844
+ try:
2845
+ p.resolve().relative_to(root_res)
2846
+ return True
2847
+ except (ValueError, OSError, RuntimeError):
2848
+ return False
2849
+
2816
2850
  current_files = {_nfc(f) for flist in full["files"].values() for f in flist}
2817
2851
  deleted_files: list[str] = []
2818
2852
  excluded_files: list[str] = []
2819
2853
  for f in manifest:
2854
+ if not _in_root(f):
2855
+ continue
2820
2856
  if _nfc(f) in current_files:
2821
2857
  continue
2822
2858
  try:
@@ -517,6 +517,7 @@ def to_cypher(G: nx.Graph, output_path: str) -> None:
517
517
  lines.append(f"MERGE (n:{ftype} {{id: '{node_id_esc}', label: '{label}'}});")
518
518
  lines.append("")
519
519
  for u, v, data in G.edges(data=True):
520
+ u, v = data.get("_src", u), data.get("_tgt", v)
520
521
  rel = _cypher_label(
521
522
  (data.get("relation", "RELATES_TO") or "RELATES_TO").upper(),
522
523
  "RELATES_TO",
@@ -1223,6 +1224,7 @@ def to_canvas(
1223
1224
  # Generate edges - only between nodes both in canvas, cap at 200 highest-weight
1224
1225
  all_edges_weighted: list[tuple[float, str, str, str]] = []
1225
1226
  for u, v, edata in G.edges(data=True):
1227
+ u, v = edata.get("_src", u), edata.get("_tgt", v)
1226
1228
  if u in all_canvas_nodes and v in all_canvas_nodes:
1227
1229
  weight = edata.get("weight", 1.0)
1228
1230
  relation = edata.get("relation", "")
@@ -91,8 +91,8 @@ def push_to_neo4j(
91
91
  session.run(
92
92
  f"MATCH (a {{id: $src}}), (b {{id: $tgt}}) "
93
93
  f"MERGE (a)-[r:{rel}]->(b) SET r += $props",
94
- src=u,
95
- tgt=v,
94
+ src=data.get("_src", u),
95
+ tgt=data.get("_tgt", v),
96
96
  props=props,
97
97
  )
98
98
  edges_pushed += 1
@@ -203,7 +203,7 @@ def push_to_falkordb(
203
203
  graph.query(
204
204
  f"MATCH (a {{id: $src}}), (b {{id: $tgt}}) "
205
205
  f"MERGE (a)-[r:{rel}]->(b) SET r += $props",
206
- {"src": u, "tgt": v, "props": props},
206
+ {"src": data.get("_src", u), "tgt": data.get("_tgt", v), "props": props},
207
207
  )
208
208
  edges_pushed += 1
209
209
 
@@ -2527,10 +2527,12 @@ def _astro_mask_non_script(src: str) -> str:
2527
2527
  chars = [c if c in "\r\n" else " " for c in src]
2528
2528
  for start, end in keep:
2529
2529
  chars[start:end] = src[start:end]
2530
- # Terminate the region in place of the following `<`, so two scripts on
2531
- # one line don't run together into a single statement.
2530
+ # End a trailing // comment before terminating the statement, as in
2531
+ # the Svelte masker. U+2028 keeps source line numbers unchanged; its
2532
+ # three UTF-8 bytes replace three ASCII bytes from the closing tag.
2533
+ # Frontmatter ends at a preserved newline and needs no terminator.
2532
2534
  if end < len(chars) and chars[end] == " ":
2533
- chars[end] = ";"
2535
+ chars[end:end + 4] = ["\u2028", ";", "", ""]
2534
2536
  return "".join(chars)
2535
2537
 
2536
2538
 
@@ -7790,7 +7792,11 @@ def extract(
7790
7792
  continue # empty / whitespace-only: nothing to model, no signal
7791
7793
  except OSError:
7792
7794
  _size = 0
7793
- _symbolless_files.append((os.path.relpath(str(_p), str(root)).replace("\\", "/"), _size))
7795
+ try:
7796
+ _display_path = os.path.relpath(str(_p), str(root)).replace("\\", "/")
7797
+ except ValueError:
7798
+ _display_path = _p.as_posix()
7799
+ _symbolless_files.append((_display_path, _size))
7794
7800
  if _symbolless_files:
7795
7801
  _total_bytes = sum(size for _, size in _symbolless_files)
7796
7802
  _total_mb = _total_bytes / (1024 * 1024)
@@ -1400,7 +1400,7 @@ def _python_collect_assignment_targets(node, source: bytes, out: set[str]) -> No
1400
1400
  # Languages whose `self`/`this` member calls bind through _self_call_target.
1401
1401
  _SELF_CALL_LANGUAGES = frozenset({
1402
1402
  "tree_sitter_python", "tree_sitter_javascript", "tree_sitter_typescript",
1403
- "tree_sitter_swift", "tree_sitter_ruby",
1403
+ "tree_sitter_swift", "tree_sitter_ruby", "tree_sitter_php",
1404
1404
  })
1405
1405
 
1406
1406
  def _self_call_target(
@@ -1413,9 +1413,9 @@ def _self_call_target(
1413
1413
  methods_by_owner: dict[tuple[str, str], str],
1414
1414
  class_bases: dict[str, list[str]],
1415
1415
  walk_bases: bool = True,
1416
+ require_method_owner: bool = False,
1416
1417
  ) -> str | None:
1417
- """In-file target of `self.m()` / `cls.m()` / `super().m()` in Python and
1418
- `this.m()` / `super.m()` in JS/TS, else None.
1418
+ """In-file target of a known current-instance or base-instance method call.
1419
1419
 
1420
1420
  ``walk_bases=False`` stops after the caller's own class and otherwise keeps
1421
1421
  the plain lookup: JS/TS `extends` edges come from the later symbol pass, so
@@ -1436,7 +1436,7 @@ def _self_call_target(
1436
1436
  scope = scope_parents.get(scope)
1437
1437
  fallback = label_to_nid.get(callee)
1438
1438
  if not scope:
1439
- return fallback
1439
+ return None if require_method_owner else fallback
1440
1440
  level = [method_owner[scope]]
1441
1441
  seen: set[str] = set()
1442
1442
  skip_own = receiver == "super"
@@ -2753,6 +2753,75 @@ def _js_scan_member_assignments(
2753
2753
  function_bodies.append((m_nid, m_body))
2754
2754
 
2755
2755
 
2756
+ def _js_find_exported_objects(program_node, source: bytes) -> set[str]:
2757
+ """Find names of identifiers exported from a JS module (CJS or ESM)."""
2758
+ if program_node is None or program_node.type != "program":
2759
+ return set()
2760
+ exported = set()
2761
+ for child in program_node.children:
2762
+ if child.type == "export_statement":
2763
+ for c in child.children:
2764
+ if c.type == "identifier":
2765
+ exported.add(_read_text(c, source))
2766
+ elif c.type == "export_clause":
2767
+ for sc in c.children:
2768
+ if sc.type == "export_specifier":
2769
+ name_node = sc.child_by_field_name("name")
2770
+ if name_node:
2771
+ exported.add(_read_text(name_node, source))
2772
+ elif c.type in ("variable_declaration", "lexical_declaration"):
2773
+ for decl in c.children:
2774
+ if decl.type == "variable_declarator":
2775
+ name_node = decl.child_by_field_name("name")
2776
+ if name_node and name_node.type == "identifier":
2777
+ exported.add(_read_text(name_node, source))
2778
+ elif child.type in ("variable_declaration", "lexical_declaration"):
2779
+ for decl in child.children:
2780
+ if decl.type != "variable_declarator":
2781
+ continue
2782
+ name_node = decl.child_by_field_name("name")
2783
+ val_node = decl.child_by_field_name("value")
2784
+ if name_node and name_node.type == "identifier" and val_node:
2785
+ name_str = _read_text(name_node, source)
2786
+ curr = val_node
2787
+ while curr and curr.type == "assignment_expression":
2788
+ left = curr.child_by_field_name("left")
2789
+ if left:
2790
+ left_str = _read_text(left, source)
2791
+ if left_str in ("module.exports", "exports") or left_str.startswith(("module.exports.", "exports.")):
2792
+ exported.add(name_str)
2793
+ break
2794
+ curr = curr.child_by_field_name("right")
2795
+ if curr:
2796
+ val_str = _read_text(curr, source)
2797
+ if val_str in ("module.exports", "exports"):
2798
+ exported.add(name_str)
2799
+ elif child.type == "expression_statement":
2800
+ assign = next((c for c in child.children if c.type == "assignment_expression"), None)
2801
+ if assign:
2802
+ left = assign.child_by_field_name("left")
2803
+ right = assign.child_by_field_name("right")
2804
+ if left:
2805
+ left_str = _read_text(left, source)
2806
+ if left_str in ("module.exports", "exports") or left_str.startswith(("module.exports.", "exports.")):
2807
+ curr = right
2808
+ while curr and curr.type == "assignment_expression":
2809
+ l = curr.child_by_field_name("left")
2810
+ if l and l.type == "identifier":
2811
+ exported.add(_read_text(l, source))
2812
+ curr = curr.child_by_field_name("right")
2813
+ if curr and curr.type == "identifier":
2814
+ exported.add(_read_text(curr, source))
2815
+ elif curr and curr.type == "object":
2816
+ for prop in curr.children:
2817
+ if prop.type == "shorthand_property_identifier":
2818
+ exported.add(_read_text(prop, source))
2819
+ elif prop.type == "pair":
2820
+ v = prop.child_by_field_name("value")
2821
+ if v and v.type == "identifier":
2822
+ exported.add(_read_text(v, source))
2823
+ return exported
2824
+
2756
2825
  def _js_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
2757
2826
  nodes: list, edges: list, seen_ids: set, function_bodies: list,
2758
2827
  parent_class_nid: str | None, add_node_fn, add_edge_fn,
@@ -2828,6 +2897,20 @@ def _js_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
2828
2897
  add_node_fn(nid, f".{member_name}()", line)
2829
2898
  add_edge_fn(owner_nid, nid, "method", line)
2830
2899
  handled = True
2900
+ elif kind == "object":
2901
+ is_exported = False
2902
+ if node.parent is not None and node.parent.type == "program":
2903
+ exported_names = _js_find_exported_objects(node.parent, source)
2904
+ is_exported = owner_name in exported_names
2905
+ if is_exported:
2906
+ owner_nid = _make_id(stem, owner_name)
2907
+ nid = _make_id(owner_nid, member_name)
2908
+ if owner_nid not in seen_ids:
2909
+ add_node_fn(owner_nid, owner_name, line)
2910
+ add_edge_fn(file_nid, owner_nid, "contains", line)
2911
+ add_node_fn(nid, f".{member_name}()", line)
2912
+ add_edge_fn(owner_nid, nid, "method", line)
2913
+ handled = True
2831
2914
  if handled:
2832
2915
  if callable_def_nids is not None:
2833
2916
  callable_def_nids.add(nid) # CJS/prototype fn is callable
@@ -4364,6 +4447,10 @@ def _extract_generic(
4364
4447
 
4365
4448
  file_nid = _make_id(str(path))
4366
4449
  add_node(file_nid, path.name, 1)
4450
+ if not source:
4451
+ # #4041: a zero-byte file has no line 1. Keep the node (an empty
4452
+ # __init__.py is still a module others import) but leave it unanchored.
4453
+ next(n for n in nodes if n["id"] == file_nid)["source_location"] = None
4367
4454
  if config.ts_module == "tree_sitter_ruby":
4368
4455
  file_node = next(n for n in nodes if n["id"] == file_nid)
4369
4456
  file_metadata = {"ruby_resolution_schema": 1}
@@ -5056,6 +5143,22 @@ def _extract_generic(
5056
5143
  if target_nid != class_nid:
5057
5144
  add_edge(class_nid, target_nid, "references",
5058
5145
  cp_line, context=ctx)
5146
+ # Class-level context bounds (`class Foo[A: Ordering]`, also on
5147
+ # traits and enums) are the same typeclass dependency as the
5148
+ # method-level case (#2046), so they get the same `type_bound`
5149
+ # context, attributed to the class (#4080).
5150
+ for c in node.children:
5151
+ if c.type != "type_parameters":
5152
+ continue
5153
+ bound_refs: list[tuple[str, str]] = []
5154
+ _scala_collect_context_bounds(c, source, bound_refs)
5155
+ for ref_name, role in bound_refs:
5156
+ ctx = ("generic_arg" if role == "generic_arg"
5157
+ else "type_bound")
5158
+ target_nid = ensure_named_node(ref_name, line)
5159
+ if target_nid != class_nid:
5160
+ add_edge(class_nid, target_nid, "references",
5161
+ line, context=ctx)
5059
5162
 
5060
5163
  # C#: a primary constructor (`class Foo(IBar bar)`, C# 12+) declares
5061
5164
  # its dependencies on the type declaration itself rather than in a
@@ -6532,6 +6635,8 @@ def _extract_generic(
6532
6635
  if e["relation"] == "method":
6533
6636
  method_owner[e["target"]] = e["source"]
6534
6637
  name = label_by_nid.get(e["target"], "").strip("()").lstrip(".")
6638
+ if config.ts_module == "tree_sitter_php":
6639
+ name = name.casefold()
6535
6640
  methods_by_owner.setdefault((e["source"], name), e["target"])
6536
6641
 
6537
6642
  def _fields_up_chain(tables: dict, class_nid) -> dict:
@@ -7099,6 +7204,12 @@ def _extract_generic(
7099
7204
  name_node = node.child_by_field_name("name")
7100
7205
  if name_node:
7101
7206
  callee_name = _read_text(name_node, source)
7207
+ receiver = node.child_by_field_name("object")
7208
+ if (receiver is not None
7209
+ and _read_text(receiver, source) == "$this"
7210
+ and callee_name
7211
+ and callee_name.casefold() in _LANGUAGE_BUILTIN_GLOBALS):
7212
+ self_receiver = "this"
7102
7213
  elif config.ts_module == "tree_sitter_cpp":
7103
7214
  # C++: function field, then field_expression/qualified_identifier
7104
7215
  func_node = node.child_by_field_name(config.call_function_field) if config.call_function_field else None
@@ -7288,7 +7399,9 @@ def _extract_generic(
7288
7399
  # receiver-typed defers just past this comment) means it can only ever
7289
7400
  # reach an edge through a guarded, receiver-typed resolver, never the
7290
7401
  # unguarded bare-name path a real god node would need.
7402
+ # A known PHP $this receiver resolves against its owning class's methods.
7291
7403
  _builtin_member_call = is_member_call and callee_name in _LANGUAGE_BUILTIN_GLOBALS
7404
+ php_builtin_self_call = config.ts_module == "tree_sitter_php" and self_receiver == "this"
7292
7405
  if callee_name and (
7293
7406
  callee_name not in _LANGUAGE_BUILTIN_GLOBALS or _builtin_member_call
7294
7407
  ):
@@ -7329,7 +7442,7 @@ def _extract_generic(
7329
7442
  and is_member_call
7330
7443
  and not lua_self_qualified
7331
7444
  )
7332
- if _python_defer or _java_defer or _builtin_member_call or _lua_member_defer or (
7445
+ if _python_defer or _java_defer or (_builtin_member_call and not php_builtin_self_call) or _lua_member_defer or (
7333
7446
  is_member_call
7334
7447
  and member_receiver
7335
7448
  and (
@@ -7356,13 +7469,17 @@ def _extract_generic(
7356
7469
  and member_receiver in ("self", "cls", "super")
7357
7470
  ):
7358
7471
  tgt_nid = _self_call_target(
7359
- caller_nid, callee_name, self_receiver or member_receiver or "",
7472
+ caller_nid, callee_name.casefold() if php_builtin_self_call else callee_name,
7473
+ self_receiver or member_receiver or "",
7360
7474
  label_to_nid, scope_parents, method_owner, methods_by_owner,
7361
7475
  _local_bases,
7362
7476
  walk_bases=config.ts_module not in (
7363
7477
  "tree_sitter_javascript", "tree_sitter_typescript",
7364
7478
  ),
7479
+ require_method_owner=php_builtin_self_call,
7365
7480
  )
7481
+ if php_builtin_self_call and tgt_nid not in method_owner:
7482
+ tgt_nid = None
7366
7483
  else:
7367
7484
  tgt_nid = label_to_nid.get(callee_name)
7368
7485
  # A qualified `new A.B.Foo()` whose bare name matches only a
@@ -226,6 +226,30 @@ def extract_objc(path: Path) -> dict:
226
226
  if entry is not None:
227
227
  _record_field_type(cls_nid, *entry)
228
228
 
229
+ def _emit_enum(enum_spec, name: str, line: int) -> None:
230
+ """Emit a C-style enum type node plus a node + `case_of` edge per
231
+ enumerator, mirroring how every other language with enums models them
232
+ (Java #1719, C++ #3939, Swift). Objective-C is an object-oriented
233
+ extractor that already emits @interface/@protocol types, but plain
234
+ `enum`/`typedef enum` definitions were dropped entirely.
235
+ """
236
+ enum_nid = _make_id(stem, name)
237
+ add_node(enum_nid, name, line)
238
+ add_edge(file_nid, enum_nid, "contains", line)
239
+ body = next((c for c in enum_spec.children if c.type == "enumerator_list"), None)
240
+ if body is None:
241
+ return
242
+ for member in body.children:
243
+ if member.type != "enumerator":
244
+ continue
245
+ mname = next((_read(c) for c in member.children if c.type == "identifier"), None)
246
+ if not mname:
247
+ continue
248
+ m_line = member.start_point[0] + 1
249
+ member_nid = _make_id(enum_nid, mname)
250
+ add_node(member_nid, mname, m_line)
251
+ add_edge(enum_nid, member_nid, "case_of", m_line)
252
+
229
253
  def walk(node, parent_nid: str | None = None) -> None:
230
254
  t = node.type
231
255
  line = node.start_point[0] + 1
@@ -408,6 +432,42 @@ def extract_objc(path: Path) -> dict:
408
432
  method_bodies.append((method_nid, node, container))
409
433
  return
410
434
 
435
+ if t == "type_definition":
436
+ # `typedef enum { ... } Name;` / `typedef enum Tag { ... } Name;`.
437
+ # The enum body sits on a child enum_specifier that carries no usable
438
+ # name; the name callers reference is the typedef alias (the trailing
439
+ # type_identifier). NS_ENUM/NS_OPTIONS never reach here — they are
440
+ # macro_type_specifiers that tree-sitter parses into ERROR subtrees,
441
+ # so they remain unsupported.
442
+ enum_spec = next((c for c in node.children if c.type == "enum_specifier"), None)
443
+ if enum_spec is not None and any(
444
+ c.type == "enumerator_list" for c in enum_spec.children
445
+ ):
446
+ alias = next(
447
+ (_read(c) for c in reversed(node.children) if c.type == "type_identifier"),
448
+ None,
449
+ )
450
+ if alias is None:
451
+ alias = next(
452
+ (_read(c) for c in enum_spec.children if c.type == "type_identifier"),
453
+ None,
454
+ )
455
+ if alias:
456
+ _emit_enum(enum_spec, alias, line)
457
+ return
458
+ # Not an enum typedef: fall through to the generic recursion.
459
+
460
+ if t == "enum_specifier":
461
+ # A named C-style enum definition: `enum Color { Red, Green };`. Skip
462
+ # a bare reference / forward declaration (no enumerator_list) and an
463
+ # anonymous enum (no name): neither is a nameable definition.
464
+ name = next(
465
+ (_read(c) for c in node.children if c.type == "type_identifier"), None
466
+ )
467
+ if name and any(c.type == "enumerator_list" for c in node.children):
468
+ _emit_enum(node, name, line)
469
+ return
470
+
411
471
  for child in node.children:
412
472
  walk(child, parent_nid)
413
473