graphifyy 0.9.78__tar.gz → 0.9.80__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 (587) hide show
  1. {graphifyy-0.9.78/graphifyy.egg-info → graphifyy-0.9.80}/PKG-INFO +2 -2
  2. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/build.py +130 -8
  3. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cache.py +44 -1
  4. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cli.py +13 -1
  5. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/detect.py +80 -5
  6. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extract.py +141 -14
  7. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/engine.py +283 -0
  8. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/markdown.py +56 -7
  9. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/resolution.py +7 -1
  10. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/paths.py +16 -5
  11. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/serve.py +88 -36
  12. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/watch.py +46 -6
  13. {graphifyy-0.9.78 → graphifyy-0.9.80/graphifyy.egg-info}/PKG-INFO +2 -2
  14. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphifyy.egg-info/SOURCES.txt +7 -0
  15. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphifyy.egg-info/requires.txt +1 -1
  16. {graphifyy-0.9.78 → graphifyy-0.9.80}/pyproject.toml +9 -2
  17. graphifyy-0.9.80/tests/test_cache_stale_import_target.py +107 -0
  18. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_detect.py +231 -0
  19. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_erlang_extractor.py +19 -0
  20. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_external_stub_endpoints.py +107 -0
  21. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extract.py +137 -0
  22. graphifyy-0.9.80/tests/test_extract_path_memo.py +67 -0
  23. graphifyy-0.9.80/tests/test_java_anonymous_class.py +102 -0
  24. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_import_resolution.py +22 -0
  25. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_languages.py +62 -0
  26. graphifyy-0.9.80/tests/test_mcp_graph_view_cache.py +124 -0
  27. graphifyy-0.9.80/tests/test_no_cluster_run_only_keys.py +60 -0
  28. graphifyy-0.9.80/tests/test_no_cluster_undeclared_endpoints.py +122 -0
  29. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ollama_retry_cap.py +5 -0
  30. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_partial_extraction_warning.py +33 -0
  31. graphifyy-0.9.80/tests/test_python_typed_receiver_calls.py +167 -0
  32. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_r_extractor.py +22 -0
  33. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_serve_http.py +107 -0
  34. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_solidity_extractor.py +17 -0
  35. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_source_file_encoding.py +10 -3
  36. graphifyy-0.9.80/tests/test_type_only_import_cycles.py +321 -0
  37. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_vbnet_extractor.py +18 -0
  38. graphifyy-0.9.78/tests/test_type_only_import_cycles.py +0 -133
  39. {graphifyy-0.9.78 → graphifyy-0.9.80}/LICENSE +0 -0
  40. {graphifyy-0.9.78 → graphifyy-0.9.80}/LICENSE-MIT +0 -0
  41. {graphifyy-0.9.78 → graphifyy-0.9.80}/NOTICE +0 -0
  42. {graphifyy-0.9.78 → graphifyy-0.9.80}/README.md +0 -0
  43. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/__init__.py +0 -0
  44. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/__main__.py +0 -0
  45. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/_minhash.py +0 -0
  46. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/affected.py +0 -0
  47. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/agents-md.md +0 -0
  48. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/antigravity-rules.md +0 -0
  49. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/claude-md.md +0 -0
  50. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/gemini-md.md +0 -0
  51. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/kiro-steering.md +0 -0
  52. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/always_on/vscode-instructions.md +0 -0
  53. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/analyze.py +0 -0
  54. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/benchmark.py +0 -0
  55. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/callflow_html.py +0 -0
  56. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cargo_introspect.py +0 -0
  57. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cluster.py +0 -0
  58. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/command-kilo.md +0 -0
  59. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cross_repo_calls.py +0 -0
  60. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/cross_repo_types.py +0 -0
  61. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/csharp_dispatch.py +0 -0
  62. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/dedup.py +0 -0
  63. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/diagnostics.py +0 -0
  64. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/export.py +0 -0
  65. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/exporters/__init__.py +0 -0
  66. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/exporters/base.py +0 -0
  67. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/exporters/graphdb.py +0 -0
  68. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/exporters/html.py +0 -0
  69. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/__init__.py +0 -0
  70. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/apex.py +0 -0
  71. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/base.py +0 -0
  72. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/bash.py +0 -0
  73. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/blade.py +0 -0
  74. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/cobol.py +0 -0
  75. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/commonlisp.py +0 -0
  76. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/csharp.py +0 -0
  77. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/dart.py +0 -0
  78. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/dm.py +0 -0
  79. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/elixir.py +0 -0
  80. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/erlang.py +0 -0
  81. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/fortran.py +0 -0
  82. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/go.py +0 -0
  83. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/json_config.py +0 -0
  84. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/julia.py +0 -0
  85. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/models.py +0 -0
  86. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/objc.py +0 -0
  87. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/ocaml.py +0 -0
  88. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/pascal.py +0 -0
  89. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/pascal_forms.py +0 -0
  90. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/powershell.py +0 -0
  91. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/r.py +0 -0
  92. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/razor.py +0 -0
  93. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/robot.py +0 -0
  94. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/rust.py +0 -0
  95. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/sln.py +0 -0
  96. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/solidity.py +0 -0
  97. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/sql.py +0 -0
  98. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/terraform.py +0 -0
  99. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/vbnet.py +0 -0
  100. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/verilog.py +0 -0
  101. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/extractors/zig.py +0 -0
  102. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/file_slice.py +0 -0
  103. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/global_graph.py +0 -0
  104. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/google_workspace.py +0 -0
  105. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/hooks.py +0 -0
  106. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/ids.py +0 -0
  107. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/ingest.py +0 -0
  108. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/install.py +0 -0
  109. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/interface_dispatch.py +0 -0
  110. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/llm.py +0 -0
  111. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/manifest.py +0 -0
  112. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/manifest_ingest.py +0 -0
  113. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/markdown_resolution.py +0 -0
  114. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/mcp_ingest.py +0 -0
  115. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/multigraph_compat.py +0 -0
  116. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/pascal_resolution.py +0 -0
  117. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/pg_introspect.py +0 -0
  118. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/prs.py +0 -0
  119. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/querylog.py +0 -0
  120. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/reflect.py +0 -0
  121. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/report.py +0 -0
  122. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/resolver_registry.py +0 -0
  123. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/ruby_resolution.py +0 -0
  124. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/scip_ingest.py +0 -0
  125. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/security.py +0 -0
  126. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/semantic_cleanup.py +0 -0
  127. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-agents.md +0 -0
  128. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-aider.md +0 -0
  129. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-amp.md +0 -0
  130. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-claw.md +0 -0
  131. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-codex.md +0 -0
  132. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-copilot.md +0 -0
  133. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-devin.md +0 -0
  134. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-droid.md +0 -0
  135. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-kilo.md +0 -0
  136. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-kiro.md +0 -0
  137. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-opencode.md +0 -0
  138. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-pi.md +0 -0
  139. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-trae.md +0 -0
  140. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-vscode.md +0 -0
  141. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill-windows.md +0 -0
  142. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skill.md +0 -0
  143. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/add-watch.md +0 -0
  144. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/exports.md +0 -0
  145. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/extraction-spec.md +0 -0
  146. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/github-and-merge.md +0 -0
  147. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/hooks.md +0 -0
  148. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/query.md +0 -0
  149. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/transcribe.md +0 -0
  150. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/agents/references/update.md +0 -0
  151. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/add-watch.md +0 -0
  152. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/exports.md +0 -0
  153. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/extraction-spec.md +0 -0
  154. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/github-and-merge.md +0 -0
  155. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/hooks.md +0 -0
  156. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/query.md +0 -0
  157. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/transcribe.md +0 -0
  158. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/amp/references/update.md +0 -0
  159. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/add-watch.md +0 -0
  160. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/exports.md +0 -0
  161. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/extraction-spec.md +0 -0
  162. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/github-and-merge.md +0 -0
  163. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/hooks.md +0 -0
  164. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/query.md +0 -0
  165. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/transcribe.md +0 -0
  166. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claude/references/update.md +0 -0
  167. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/add-watch.md +0 -0
  168. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/exports.md +0 -0
  169. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/extraction-spec.md +0 -0
  170. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/github-and-merge.md +0 -0
  171. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/hooks.md +0 -0
  172. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/query.md +0 -0
  173. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/transcribe.md +0 -0
  174. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/claw/references/update.md +0 -0
  175. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/add-watch.md +0 -0
  176. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/exports.md +0 -0
  177. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/extraction-spec.md +0 -0
  178. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/github-and-merge.md +0 -0
  179. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/hooks.md +0 -0
  180. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/query.md +0 -0
  181. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/transcribe.md +0 -0
  182. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/codex/references/update.md +0 -0
  183. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/add-watch.md +0 -0
  184. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/exports.md +0 -0
  185. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/extraction-spec.md +0 -0
  186. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/github-and-merge.md +0 -0
  187. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/hooks.md +0 -0
  188. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/query.md +0 -0
  189. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/transcribe.md +0 -0
  190. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/copilot/references/update.md +0 -0
  191. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/add-watch.md +0 -0
  192. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/exports.md +0 -0
  193. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/extraction-spec.md +0 -0
  194. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/github-and-merge.md +0 -0
  195. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/hooks.md +0 -0
  196. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/query.md +0 -0
  197. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/transcribe.md +0 -0
  198. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/droid/references/update.md +0 -0
  199. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/add-watch.md +0 -0
  200. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/exports.md +0 -0
  201. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/extraction-spec.md +0 -0
  202. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/github-and-merge.md +0 -0
  203. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/hooks.md +0 -0
  204. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/query.md +0 -0
  205. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/transcribe.md +0 -0
  206. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kilo/references/update.md +0 -0
  207. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/add-watch.md +0 -0
  208. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/exports.md +0 -0
  209. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/extraction-spec.md +0 -0
  210. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/github-and-merge.md +0 -0
  211. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/hooks.md +0 -0
  212. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/query.md +0 -0
  213. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/transcribe.md +0 -0
  214. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/kiro/references/update.md +0 -0
  215. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/add-watch.md +0 -0
  216. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/exports.md +0 -0
  217. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/extraction-spec.md +0 -0
  218. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/github-and-merge.md +0 -0
  219. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/hooks.md +0 -0
  220. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/query.md +0 -0
  221. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/transcribe.md +0 -0
  222. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/opencode/references/update.md +0 -0
  223. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/add-watch.md +0 -0
  224. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/exports.md +0 -0
  225. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/extraction-spec.md +0 -0
  226. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/github-and-merge.md +0 -0
  227. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/hooks.md +0 -0
  228. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/query.md +0 -0
  229. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/transcribe.md +0 -0
  230. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/pi/references/update.md +0 -0
  231. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/add-watch.md +0 -0
  232. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/exports.md +0 -0
  233. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/extraction-spec.md +0 -0
  234. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/github-and-merge.md +0 -0
  235. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/hooks.md +0 -0
  236. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/query.md +0 -0
  237. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/transcribe.md +0 -0
  238. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/trae/references/update.md +0 -0
  239. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/add-watch.md +0 -0
  240. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/exports.md +0 -0
  241. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/extraction-spec.md +0 -0
  242. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/github-and-merge.md +0 -0
  243. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/hooks.md +0 -0
  244. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/query.md +0 -0
  245. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/transcribe.md +0 -0
  246. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/vscode/references/update.md +0 -0
  247. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/add-watch.md +0 -0
  248. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/exports.md +0 -0
  249. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/extraction-spec.md +0 -0
  250. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/github-and-merge.md +0 -0
  251. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/hooks.md +0 -0
  252. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/query.md +0 -0
  253. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/transcribe.md +0 -0
  254. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/skills/windows/references/update.md +0 -0
  255. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/swift_dispatch.py +0 -0
  256. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/symbol_resolution.py +0 -0
  257. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/transcribe.py +0 -0
  258. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/tree_html.py +0 -0
  259. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/validate.py +0 -0
  260. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphify/wiki.py +0 -0
  261. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphifyy.egg-info/dependency_links.txt +0 -0
  262. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphifyy.egg-info/entry_points.txt +0 -0
  263. {graphifyy-0.9.78 → graphifyy-0.9.80}/graphifyy.egg-info/top_level.txt +0 -0
  264. {graphifyy-0.9.78 → graphifyy-0.9.80}/setup.cfg +0 -0
  265. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_affected_cli.py +0 -0
  266. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_affected_member_seed.py +0 -0
  267. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_agents_platform.py +0 -0
  268. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_analyze.py +0 -0
  269. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_anthropic_custom_endpoint.py +0 -0
  270. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_antigravity_install.py +0 -0
  271. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_apm_fallback_version.py +0 -0
  272. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_architecture_doc.py +0 -0
  273. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_astro_extraction.py +0 -0
  274. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_astro_import_ids.py +0 -0
  275. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_atomic_canvas_export.py +0 -0
  276. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_atomic_version_stamp.py +0 -0
  277. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_atomic_writes.py +0 -0
  278. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_backend_env_isolation.py +0 -0
  279. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_backend_extras.py +0 -0
  280. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_benchmark.py +0 -0
  281. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_benchmark_raw_graph.py +0 -0
  282. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_blade_extractor.py +0 -0
  283. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_build.py +0 -0
  284. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_build_located_semantic_identity.py +0 -0
  285. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_build_merge_dedup_scope.py +0 -0
  286. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_build_merge_hyperedges_and_prune.py +0 -0
  287. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_build_merge_shrink_guard.py +0 -0
  288. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_builtin_global_type_refs.py +0 -0
  289. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cache.py +0 -0
  290. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_callflow_html.py +0 -0
  291. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cargo_introspect.py +0 -0
  292. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cargo_missing_manifest.py +0 -0
  293. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_carried_hyperedge_remap.py +0 -0
  294. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_case_sensitive_resolution.py +0 -0
  295. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_charmap_encoding.py +0 -0
  296. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_chunking.py +0 -0
  297. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cjs_module_extension.py +0 -0
  298. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_claude_cli_backend.py +0 -0
  299. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_claude_md.py +0 -0
  300. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cli_broken_pipe.py +0 -0
  301. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cli_export.py +0 -0
  302. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cli_help.py +0 -0
  303. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cluster.py +0 -0
  304. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cluster_exclude_hubs.py +0 -0
  305. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cobol_extractor.py +0 -0
  306. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_codebuddy.py +0 -0
  307. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_community_hub_labels.py +0 -0
  308. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_community_labels_skill.py +0 -0
  309. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_confidence.py +0 -0
  310. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_corrupt_graph_json.py +0 -0
  311. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cpp_method_declarations.py +0 -0
  312. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cpp_nested_and_cli.py +0 -0
  313. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cpp_objc_cross_file_calls.py +0 -0
  314. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cpp_preprocess.py +0 -0
  315. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cross_extension_reexport_self_cycle.py +0 -0
  316. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cross_language_call_resolution.py +0 -0
  317. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cross_repo_external_call_guards.py +0 -0
  318. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cross_repo_member_calls.py +0 -0
  319. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_cross_repo_shared_types.py +0 -0
  320. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_call_site_generic_args.py +0 -0
  321. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_enum_members.py +0 -0
  322. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_field_generic_args.py +0 -0
  323. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_generic_callsites.py +0 -0
  324. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_interface_dispatch.py +0 -0
  325. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_member_calls.py +0 -0
  326. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_member_nodes.py +0 -0
  327. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_object_creation.py +0 -0
  328. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_partial_classes.py +0 -0
  329. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_tuple_type_refs.py +0 -0
  330. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_csharp_type_resolution.py +0 -0
  331. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dart.py +0 -0
  332. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dedup.py +0 -0
  333. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dedup_remaps_hyperedges.py +0 -0
  334. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dedup_shrink_refuses_force_write.py +0 -0
  335. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dedup_survivor_richness.py +0 -0
  336. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_definition_file_portability.py +0 -0
  337. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_devin.py +0 -0
  338. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_docx_to_markdown.py +0 -0
  339. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_dotnet.py +0 -0
  340. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_duplicate_annotation_edges.py +0 -0
  341. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_elixir_import_resolution.py +0 -0
  342. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_elixir_unqualified_call_scope.py +0 -0
  343. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_evidence_binding.py +0 -0
  344. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_explain_cli.py +0 -0
  345. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_export.py +0 -0
  346. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_export_control_characters.py +0 -0
  347. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_export_direction.py +0 -0
  348. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_export_idempotent_writes.py +0 -0
  349. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_export_path_length.py +0 -0
  350. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extract_cache_location.py +0 -0
  351. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extract_cli.py +0 -0
  352. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extract_code_only_cli.py +0 -0
  353. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extract_php_closures.py +0 -0
  354. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extraction_spec_ids.py +0 -0
  355. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_extractors_registry.py +0 -0
  356. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_falkordb_integration.py +0 -0
  357. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_file_label_disambiguation.py +0 -0
  358. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_file_node_id_spec.py +0 -0
  359. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_file_slice.py +0 -0
  360. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_file_truncation_warning.py +0 -0
  361. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_forwarding_review_findings.py +0 -0
  362. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_gemini_hook.py +0 -0
  363. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_global_add_tag_inference.py +0 -0
  364. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_global_graph.py +0 -0
  365. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_go_builtin_call_targets.py +0 -0
  366. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_go_import_repoint.py +0 -0
  367. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_go_interface_methods.py +0 -0
  368. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_go_qualified_resolution.py +0 -0
  369. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_god_nodes_cli.py +0 -0
  370. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_god_nodes_exclude_hubs.py +0 -0
  371. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_google_workspace.py +0 -0
  372. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_graphdb_push_indexes.py +0 -0
  373. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hollow_chunks_arm_shrink_guard.py +0 -0
  374. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_home_sandbox.py +0 -0
  375. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hook_chain_survives_skip.py +0 -0
  376. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hook_guard.py +0 -0
  377. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hook_guard_token_match.py +0 -0
  378. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hook_out_of_project_paths.py +0 -0
  379. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hook_strict.py +0 -0
  380. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hooks.py +0 -0
  381. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hyperedge_member_shapes.py +0 -0
  382. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hyperedge_roundtrip.py +0 -0
  383. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_hypergraph.py +0 -0
  384. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_id_normalization_contract.py +0 -0
  385. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ignore_file_encoding.py +0 -0
  386. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_image_vision.py +0 -0
  387. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_import_extension_resolution.py +0 -0
  388. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_import_self_loops.py +0 -0
  389. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_imported_export_forwarding.py +0 -0
  390. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_incomplete_build_guard.py +0 -0
  391. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_incremental.py +0 -0
  392. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_incremental_mtime_collision.py +0 -0
  393. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_incremental_unscanned_placeholders.py +0 -0
  394. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_arrow_single_param_shadow.py +0 -0
  395. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_block_scoped_shadow.py +0 -0
  396. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_catch_binding_shadow.py +0 -0
  397. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_external_import_shadow.py +0 -0
  398. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_for_of_binding_shadow.py +0 -0
  399. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_function_expression_shadow.py +0 -0
  400. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_call_nested_closure_shadow.py +0 -0
  401. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_dispatch.py +0 -0
  402. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_dispatch_assign_return.py +0 -0
  403. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_indirect_dispatch_getattr.py +0 -0
  404. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_inferred_confidence_rubric.py +0 -0
  405. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ingest.py +0 -0
  406. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ingest_url_type.py +0 -0
  407. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_inherited_field_receivers.py +0 -0
  408. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_injection_sentinel_coverage.py +0 -0
  409. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install.py +0 -0
  410. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_references.py +0 -0
  411. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_roundtrip.py +0 -0
  412. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_strings.py +0 -0
  413. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_upgrade.py +0 -0
  414. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_version_stamp.py +0 -0
  415. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_install_version_warning.py +0 -0
  416. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_issue_3405_python_resolution.py +0 -0
  417. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_issue_3472_source_file_collision.py +0 -0
  418. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_java_enum_members.py +0 -0
  419. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_java_member_calls.py +0 -0
  420. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_java_type_resolution.py +0 -0
  421. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_callback_calls.py +0 -0
  422. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_destructured_export.py +0 -0
  423. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_dynamic_import_affected.py +0 -0
  424. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_dynamic_imports.py +0 -0
  425. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_exported_fn_call_resolution.py +0 -0
  426. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_exported_scalar_bindings.py +0 -0
  427. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_module_level_anonymous_calls.py +0 -0
  428. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_js_this_member_expressions.py +0 -0
  429. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_jsconfig_baseurl.py +0 -0
  430. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_json_schema_config.py +0 -0
  431. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_jsx_component_usage_calls.py +0 -0
  432. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_kotlin_grammar.py +0 -0
  433. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_kotlin_object_literal.py +0 -0
  434. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_label_retry.py +0 -0
  435. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_labeling.py +0 -0
  436. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_language_resolvers.py +0 -0
  437. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_llm_backends.py +0 -0
  438. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_llm_parser.py +0 -0
  439. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_llm_parser_reasoning.py +0 -0
  440. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_long_path_hashing.py +0 -0
  441. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_loose_sibling_import_resolution.py +0 -0
  442. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_lua_import.py +0 -0
  443. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_lua_method_calls.py +0 -0
  444. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_manifest_ingest.py +0 -0
  445. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_manifest_tomli_required.py +0 -0
  446. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_markdown_code_spans.py +0 -0
  447. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_mcp_ingest.py +0 -0
  448. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_merge_chunks_validation.py +0 -0
  449. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_merge_graphs_cli.py +0 -0
  450. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_minhash.py +0 -0
  451. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_multigraph_compat.py +0 -0
  452. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_multigraph_diagnostics.py +0 -0
  453. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_multilang.py +0 -0
  454. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_no_dedup_flag.py +0 -0
  455. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_node_id_canonical.py +0 -0
  456. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_non_regular_files.py +0 -0
  457. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_non_string_node_ids.py +0 -0
  458. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_objc_category_interfaces.py +0 -0
  459. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_objc_enum_declarations.py +0 -0
  460. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_objc_field_table_remap.py +0 -0
  461. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_objc_member_calls.py +0 -0
  462. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_objc_property_ivar_receivers.py +0 -0
  463. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_obsidian_dangling_member.py +0 -0
  464. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_obsidian_filename_cap.py +0 -0
  465. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_obsidian_unicode_tags.py +0 -0
  466. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_obsidian_vault_migration.py +0 -0
  467. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ocaml.py +0 -0
  468. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_office_incremental.py +0 -0
  469. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_office_limits.py +0 -0
  470. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ollama.py +0 -0
  471. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_openai_custom_endpoint.py +0 -0
  472. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_out_dir_evidence.py +0 -0
  473. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_oversized_document_slicing.py +0 -0
  474. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_owned_type_sources.py +0 -0
  475. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_package_json_subpath_imports.py +0 -0
  476. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_partial_cache.py +0 -0
  477. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pascal.py +0 -0
  478. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pascal_call_scoping.py +0 -0
  479. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pascal_resolution.py +0 -0
  480. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_path_cli.py +0 -0
  481. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_paths.py +0 -0
  482. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pdf_extra_warning.py +0 -0
  483. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pdf_slicing.py +0 -0
  484. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pdf_token_estimate.py +0 -0
  485. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pg_introspect.py +0 -0
  486. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_phantom_cross_package_call.py +0 -0
  487. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_phantom_external_import.py +0 -0
  488. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_php_language_construct_calls.py +0 -0
  489. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_php_object_creation.py +0 -0
  490. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_php_type_resolution.py +0 -0
  491. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pin_hash_seed.py +0 -0
  492. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_pipeline.py +0 -0
  493. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_provider_registry.py +0 -0
  494. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_prs.py +0 -0
  495. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_prune_sweeps_orphans.py +0 -0
  496. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_python_decorators.py +0 -0
  497. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_python_import_resolution.py +0 -0
  498. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_python_parse_memoization.py +0 -0
  499. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_python_underscore_resolution.py +0 -0
  500. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_query_cli.py +0 -0
  501. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_query_induced_edges.py +0 -0
  502. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_query_mcp_direction.py +0 -0
  503. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_query_names_its_graph.py +0 -0
  504. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_querylog.py +0 -0
  505. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_rationale.py +0 -0
  506. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_read_hook.py +0 -0
  507. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_reflect.py +0 -0
  508. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_relation_collapse_precedence.py +0 -0
  509. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_replace_or_append_section.py +0 -0
  510. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_report.py +0 -0
  511. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_report_gap_thresholds.py +0 -0
  512. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_resolve_memoization.py +0 -0
  513. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ruby_bare_self_send_calls.py +0 -0
  514. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ruby_resolution.py +0 -0
  515. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_rust_anonymous_const.py +0 -0
  516. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_rust_builtin_type_hubs.py +0 -0
  517. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_rust_macro_rules.py +0 -0
  518. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_rust_self_member_calls.py +0 -0
  519. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scala_abstract_methods.py +0 -0
  520. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scala_context_bounds.py +0 -0
  521. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scala_self_type.py +0 -0
  522. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scala_top_level_binding.py +0 -0
  523. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scala_type_definition.py +0 -0
  524. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_scip_ingest.py +0 -0
  525. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_search_hook.py +0 -0
  526. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_security.py +0 -0
  527. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_cache_basename_recovery.py +0 -0
  528. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_cache_out_root.py +0 -0
  529. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_cleanup.py +0 -0
  530. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_fragment_sanitize.py +0 -0
  531. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_id_remap_root.py +0 -0
  532. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_semantic_similarity.py +0 -0
  533. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_serve.py +0 -0
  534. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_settings_merge.py +0 -0
  535. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_skill_auto_refresh.py +0 -0
  536. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_skill_semantic_all_cached.py +0 -0
  537. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_skill_version_warning.py +0 -0
  538. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_skillgen.py +0 -0
  539. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_skillgen_input_path_injection.py +0 -0
  540. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_source_key_memoization.py +0 -0
  541. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_sourceless_call_targets.py +0 -0
  542. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_src_layout_import_resolution.py +0 -0
  543. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_stale_prune.py +0 -0
  544. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_stat_index_husk.py +0 -0
  545. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_stat_index_multi_root.py +0 -0
  546. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_stat_index_portability.py +0 -0
  547. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_svelte_extraction.py +0 -0
  548. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_builtin_noise.py +0 -0
  549. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_computed_properties.py +0 -0
  550. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_cross_file_calls.py +0 -0
  551. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_import_resolution.py +0 -0
  552. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_protocol_dispatch.py +0 -0
  553. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_swift_protocol_requirements.py +0 -0
  554. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_symbol_resolution.py +0 -0
  555. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_terraform.py +0 -0
  556. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_terraform_modules.py +0 -0
  557. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_trailing_newline_not_a_syntax_error.py +0 -0
  558. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_transcribe.py +0 -0
  559. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_tree_html.py +0 -0
  560. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_abstract_methods.py +0 -0
  561. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_decorators.py +0 -0
  562. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_generators.py +0 -0
  563. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_import_require.py +0 -0
  564. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_import_type_arguments.py +0 -0
  565. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_inheritance.py +0 -0
  566. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_namespace.py +0 -0
  567. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_new_expression_calls.py +0 -0
  568. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_parse_warning.py +0 -0
  569. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_ts_receiver_member_calls.py +0 -0
  570. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_typescript_enum_members.py +0 -0
  571. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_typescript_module_extensions.py +0 -0
  572. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_uninstall_scope.py +0 -0
  573. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_uninstall_symlink.py +0 -0
  574. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_unmapped_at_alias_resolution.py +0 -0
  575. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_unverified_semantic_shrink.py +0 -0
  576. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_validate.py +0 -0
  577. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_vue_extraction.py +0 -0
  578. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_walk_python_tree_iterative.py +0 -0
  579. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_watch.py +0 -0
  580. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_watch_identity_cache.py +0 -0
  581. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_watch_manifest_location.py +0 -0
  582. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_wheel_packaging.py +0 -0
  583. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_wiki.py +0 -0
  584. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_wiki_link_filename_parity.py +0 -0
  585. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_wiki_truncation_indicator.py +0 -0
  586. {graphifyy-0.9.78 → graphifyy-0.9.80}/tests/test_word_count_cache.py +0 -0
  587. {graphifyy-0.9.78 → graphifyy-0.9.80}/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.78
3
+ Version: 0.9.80
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
@@ -17,7 +17,7 @@ Requires-Dist: networkx>=3.4
17
17
  Requires-Dist: numpy>=1.21
18
18
  Requires-Dist: rapidfuzz>=3.0
19
19
  Requires-Dist: tomli>=2.0.1; python_version < "3.11"
20
- Requires-Dist: tree-sitter<0.26,>=0.23.0
20
+ Requires-Dist: tree-sitter<0.26,>=0.25
21
21
  Requires-Dist: tree-sitter-python<0.26,>=0.23
22
22
  Requires-Dist: tree-sitter-javascript<0.26,>=0.23
23
23
  Requires-Dist: tree-sitter-typescript<0.25,>=0.23
@@ -53,6 +53,21 @@ def _is_ast_tier(item: dict) -> bool:
53
53
  return isinstance(loc, str) and bool(_AST_LOC_RE.match(loc))
54
54
 
55
55
 
56
+ def _backfill_origin(item: dict) -> None:
57
+ """Stamp a loaded legacy item's tier via the _is_ast_tier shape fallback (#2334).
58
+
59
+ External import stubs are skipped, and a stamp an earlier run gave one is
60
+ removed: a stub is re-minted from its edges on every write, so a stamped
61
+ copy differed from a fresh build and, read as ``semantic``, was kept after
62
+ its last import edge was gone. Unstamped, every tier decision reads it
63
+ exactly as before (the shape fallback says non-AST).
64
+ """
65
+ if _is_external_stub(item):
66
+ item.pop("_origin", None)
67
+ return
68
+ item.setdefault("_origin", "ast" if _is_ast_tier(item) else "semantic")
69
+
70
+
56
71
  # Relations that say only "these two symbols appear together", with no claim about
57
72
  # HOW. An extractor that finds a specific fact for a pair — a call, an import, an
58
73
  # inheritance — routinely emits one of these for the same pair as well, so when the
@@ -103,6 +118,21 @@ def _mint_external_stub(G: "nx.Graph", node_set: set, nid: str) -> None:
103
118
  node_set.add(nid)
104
119
 
105
120
 
121
+ def _is_external_stub(item: dict) -> bool:
122
+ """True for a node minted by :func:`_mint_external_stub` / :func:`mint_external_stubs_in_data`.
123
+
124
+ A stub is derived from the import edges that point at it and is minted again
125
+ on every write, so it belongs to no extraction tier: the tier backfill must
126
+ not stamp it (a ``semantic`` stamp made it outlive its last import edge), and
127
+ a rebuild drops it once no edge references it.
128
+ """
129
+ return (
130
+ item.get("external") is True
131
+ and item.get("type") == "external"
132
+ and not item.get("source_file")
133
+ )
134
+
135
+
106
136
  def mint_external_stubs_in_data(data: dict) -> None:
107
137
  """Mint external stub nodes for import-family links with an undeclared target.
108
138
 
@@ -140,6 +170,69 @@ def mint_external_stubs_in_data(data: dict) -> None:
140
170
  })
141
171
  minted.add(tgt)
142
172
 
173
+
174
+ def finalize_raw_graph_endpoints(data: dict) -> None:
175
+ """Apply build_from_json's endpoint rules to a raw (``--no-cluster``) graph.
176
+
177
+ The clustered path builds the graph with :func:`build_from_json`, which mints
178
+ a typed stub for an import of an external module (#2873) and drops every
179
+ other edge it cannot attach to two declared nodes, after re-pointing an
180
+ endpoint that differs from a declared id only by normalization. The raw
181
+ write paths skip build_from_json, so graph.json kept those edges: a loader
182
+ turns each missing endpoint into an attribute-less phantom node, and a link
183
+ to a missing markdown document kept the target id the extractor built from
184
+ the absolute checkout path.
185
+
186
+ A stub is derived from the import edges that point at it, so a stub carried
187
+ over from an earlier graph that no edge references any more is dropped too;
188
+ a fresh build of the same tree would not have it.
189
+ """
190
+ mint_external_stubs_in_data(data)
191
+ nodes = data.get("nodes")
192
+ key = "links" if isinstance(data.get("links"), list) else "edges"
193
+ links = data.get(key)
194
+ if not isinstance(nodes, list) or not isinstance(links, list):
195
+ return
196
+ declared = {n.get("id") for n in nodes if isinstance(n, dict)}
197
+ norm_to_id = {_normalize_id(nid): nid for nid in declared if isinstance(nid, str)}
198
+ kept: list = []
199
+ referenced: set = set()
200
+ for e in links:
201
+ if not isinstance(e, dict):
202
+ kept.append(e)
203
+ continue
204
+ attached = True
205
+ for primary, alias in (("source", "from"), ("target", "to")):
206
+ field = primary if primary in e else alias
207
+ endpoint = e.get(field)
208
+ if isinstance(endpoint, str) and endpoint in declared:
209
+ continue
210
+ canonical = norm_to_id.get(_normalize_id(endpoint)) if isinstance(endpoint, str) else None
211
+ if canonical is None:
212
+ attached = False
213
+ break
214
+ e[field] = canonical
215
+ if attached:
216
+ kept.append(e)
217
+ referenced.add(e.get("source", e.get("from")))
218
+ referenced.add(e.get("target", e.get("to")))
219
+ links[:] = kept
220
+ for hyperedge in data.get("hyperedges", []) or []:
221
+ if isinstance(hyperedge, dict):
222
+ members = hyperedge.get("nodes", hyperedge.get("members", hyperedge.get("node_ids", [])))
223
+ if isinstance(members, list):
224
+ referenced.update(m for m in members if isinstance(m, str))
225
+ nodes[:] = [
226
+ n for n in nodes
227
+ if not (
228
+ isinstance(n, dict)
229
+ and n.get("external") is True
230
+ and n.get("type") == "external"
231
+ and not n.get("source_file")
232
+ and n.get("id") not in referenced
233
+ )
234
+ ]
235
+
143
236
  # Language interop families, keyed by extension, for the cross-language phantom-edge
144
237
  # guard in the edge loop below. Families group by REAL interop (JS/TS share a module
145
238
  # graph; C/C++/ObjC share a compilation unit via headers; JVM langs share bytecode),
@@ -650,6 +743,21 @@ def dedupe_nodes(nodes: list[dict]) -> list[dict]:
650
743
  return list(by_id.values())
651
744
 
652
745
 
746
+ def _execution_wins(a: dict, b: dict) -> None:
747
+ """Fold the ``type_only`` marker of two import edges that collapse to one.
748
+
749
+ ``type_only`` flags an import that never runs (``import type``, ``if
750
+ TYPE_CHECKING:``); ``find_import_cycles`` skips such an edge. When two edges
751
+ of one file pair collapse (``G.add_edge`` merges their attributes,
752
+ ``dedupe_edges`` keeps the first), the marker of one side would stand for a
753
+ runtime import on the other and hide its cycle. The surviving edge stays
754
+ ``type_only`` only if every import folded into it is (#3159).
755
+ """
756
+ if bool(a.get("type_only")) != bool(b.get("type_only")):
757
+ a.pop("type_only", None)
758
+ b.pop("type_only", None)
759
+
760
+
653
761
  def dedupe_edges(edges: list[dict]) -> list[dict]:
654
762
  """Collapse exact parallel edges by ``(source, target, relation)``, keeping the
655
763
  first occurrence.
@@ -660,15 +768,18 @@ def dedupe_edges(edges: list[dict]) -> list[dict]:
660
768
  duplicates accumulate and edge counts become non-deterministic across build
661
769
  modes / repeated updates (#1317). Deduping on the connectivity identity is
662
770
  zero-signal-loss and restores idempotency. Callers that intentionally keep
663
- parallel edges (multigraph output) must not use this.
771
+ parallel edges (multigraph output) must not use this. The one attribute that
772
+ is not taken from the first occurrence alone is ``type_only`` (see
773
+ :func:`_execution_wins`).
664
774
  """
665
- seen: set[tuple] = set()
775
+ seen: dict[tuple, dict] = {}
666
776
  out: list[dict] = []
667
777
  for e in edges:
668
778
  key = (e.get("source"), e.get("target"), e.get("relation"))
669
779
  if key in seen:
780
+ _execution_wins(seen[key], e)
670
781
  continue
671
- seen.add(key)
782
+ seen[key] = e
672
783
  out.append(e)
673
784
  return out
674
785
 
@@ -1423,6 +1534,20 @@ def build_from_json(extraction: dict, *, directed: bool = False, root: str | Pat
1423
1534
  # causing display functions to show edges backwards.
1424
1535
  attrs["_src"] = src
1425
1536
  attrs["_tgt"] = tgt
1537
+ # Before the drops below, so a runtime import that folds into a
1538
+ # type-only edge still clears its marker (#3159). The reverse-direction
1539
+ # duplicate that the undirected graph drops (#1061) is another file's
1540
+ # import, not this one: the surviving edge keeps its own marker.
1541
+ # `_EXTERNAL_STUB_RELATIONS` is the import family (imports, imports_from, re_exports).
1542
+ if _edge_rel in _EXTERNAL_STUB_RELATIONS and G.has_edge(src, tgt):
1543
+ _prior = G[src][tgt] # G is a plain Graph/DiGraph here, one dict per pair
1544
+ _reverse_dup = (
1545
+ not G.is_directed()
1546
+ and _prior.get("relation") == attrs.get("relation")
1547
+ and _prior.get("_src") == tgt and _prior.get("_tgt") == src
1548
+ )
1549
+ if _prior.get("relation") in _EXTERNAL_STUB_RELATIONS and not _reverse_dup:
1550
+ _execution_wins(_prior, attrs)
1426
1551
  # When the graph is undirected and the same node pair appears twice with
1427
1552
  # the same relation but opposite directions (e.g. a `calls` b and b `calls` a),
1428
1553
  # nx.Graph collapses them into one edge. The deterministic sort above means
@@ -1726,12 +1851,9 @@ def _load_existing_graph(graph_path: Path) -> "tuple[list, list, list, bool] | N
1726
1851
  # unstamped items. Stamp them via the _is_ast_tier shape fallback so the
1727
1852
  # graph self-heals on the next write and every downstream tier decision
1728
1853
  # (build_merge replace, watch reconcile) reads an explicit marker.
1729
- for item in nodes:
1730
- if isinstance(item, dict):
1731
- item.setdefault("_origin", "ast" if _is_ast_tier(item) else "semantic")
1732
- for item in edges:
1854
+ for item in nodes + edges:
1733
1855
  if isinstance(item, dict):
1734
- item.setdefault("_origin", "ast" if _is_ast_tier(item) else "semantic")
1856
+ _backfill_origin(item)
1735
1857
  return (
1736
1858
  nodes,
1737
1859
  edges,
@@ -36,7 +36,7 @@ except Exception:
36
36
  _EXTRACTOR_VERSION = "unknown"
37
37
 
38
38
  # Bump when AST cache-key semantics change independently of the package version.
39
- _AST_CACHE_SCHEMA = 5 # Python receiver-shadow facts in persisted raw calls.
39
+ _AST_CACHE_SCHEMA = 6 # Python typed-receiver facts (receiver_type) in persisted raw calls.
40
40
 
41
41
  # Version dirs already swept this process — cleanup runs once per (base, version).
42
42
  _cleaned_ast_dirs: set[str] = set()
@@ -1105,10 +1105,49 @@ def load_cached(path: Path, root: Path = Path("."), kind: str = "ast",
1105
1105
  # id-remap cannot fix because they match none of its current-path
1106
1106
  # keys. Order is free — source_file never carries the marker.
1107
1107
  _absolutize_ids_in(result, path, root)
1108
+ targets = result.pop(_CACHED_TARGETS_KEY, None)
1109
+ if isinstance(targets, list) and not all(
1110
+ _target_file_present(t, root) for t in targets if isinstance(t, str)
1111
+ ):
1112
+ return None
1108
1113
  return result
1109
1114
  return None
1110
1115
 
1111
1116
 
1117
+ # Cross-file edges (imports, re-exports, links) carry a ``target_file`` stamp
1118
+ # naming the file they resolved to. An AST entry is keyed by its own file's
1119
+ # content only, so a hit replays that resolution after the target is renamed or
1120
+ # deleted: the edge keeps the id minted from the target's absolute path, which
1121
+ # extract() maps to a portable id only for targets that exist, so the checkout
1122
+ # path reached graph.json and a warm build differed from a cold one. The entry
1123
+ # records the targets that existed when it was written; a hit whose recorded
1124
+ # target is gone is a miss and the file is extracted again.
1125
+ _CACHED_TARGETS_KEY = "_cached_target_files"
1126
+
1127
+
1128
+ def _target_file_present(target: str, root: Path) -> bool:
1129
+ candidate = Path(target)
1130
+ if not candidate.is_absolute():
1131
+ candidate = Path(root) / candidate
1132
+ try:
1133
+ return candidate.is_file()
1134
+ except (OSError, ValueError):
1135
+ return False
1136
+
1137
+
1138
+ def _present_target_files(result: dict, root: Path) -> list[str]:
1139
+ """The ``target_file`` stamps in ``result`` that name an existing file."""
1140
+ present: set[str] = set()
1141
+ for edge in result.get("edges", []) or []:
1142
+ if not isinstance(edge, dict):
1143
+ continue
1144
+ target = edge.get("target_file")
1145
+ if isinstance(target, str) and target and target not in present:
1146
+ if _target_file_present(target, root):
1147
+ present.add(target)
1148
+ return sorted(present)
1149
+
1150
+
1112
1151
  def save_cached(path: Path, result: dict, root: Path = Path("."), kind: str = "ast",
1113
1152
  cache_root: Path | None = None, prompt: "str | Path | None" = None,
1114
1153
  prompt_file: "str | Path | None" = None) -> None:
@@ -1155,6 +1194,10 @@ def save_cached(path: Path, result: dict, root: Path = Path("."), kind: str = "a
1155
1194
  if isinstance(result, dict):
1156
1195
  import copy as _copy
1157
1196
  on_disk = _copy.deepcopy(result)
1197
+ if kind == "ast":
1198
+ targets = _present_target_files(on_disk, root)
1199
+ if targets:
1200
+ on_disk[_CACHED_TARGETS_KEY] = targets
1158
1201
  _relativize_source_files_in(on_disk, root)
1159
1202
  # Then replace the absolute root inside the ids and remaining paths, so
1160
1203
  # the entry replays portably under any root (#2257). Strictly after the
@@ -4515,6 +4515,11 @@ def dispatch_command(cmd: str) -> None:
4515
4515
  # gets this), so apply it directly on the merged node list.
4516
4516
  from graphify.build import disambiguate_file_labels_in_nodes as _disamb_labels
4517
4517
  _disamb_labels(merged["nodes"])
4518
+ # Same endpoint rules as build_from_json (#2873): an import of an
4519
+ # external module gets a typed stub node, and any other edge without
4520
+ # two declared endpoints is dropped instead of shipping a phantom.
4521
+ from graphify.build import finalize_raw_graph_endpoints as _finalize_raw_graph_endpoints
4522
+ _finalize_raw_graph_endpoints(merged)
4518
4523
  # Backfill source_file from endpoint nodes — this raw path bypasses
4519
4524
  # build_from_json's backfill, and semantic edges sometimes omit it (#1279).
4520
4525
  _node_sf = {n.get("id"): n.get("source_file") for n in merged["nodes"]}
@@ -4552,7 +4557,14 @@ def dispatch_command(cmd: str) -> None:
4552
4557
  _backup(graphify_out)
4553
4558
  _invalidate_file_manifest_for_db_graph()
4554
4559
  from graphify.paths import write_json_atomic as _write_json_atomic
4555
- _write_json_atomic(graph_json_path, merged, indent=2)
4560
+ from graphify.extract import RUN_ONLY_EXTRACTION_KEYS as _RUN_ONLY_KEYS
4561
+ # merge_raw_extraction above has consumed them; graph.json must not
4562
+ # carry this run's absolute input paths.
4563
+ _write_json_atomic(
4564
+ graph_json_path,
4565
+ {k: v for k, v in merged.items() if k not in _RUN_ONLY_KEYS},
4566
+ indent=2,
4567
+ )
4556
4568
  try:
4557
4569
  # Record the scan root so a later build_merge / update runbook can
4558
4570
  # relativize deleted-file paths correctly even for a custom --out
@@ -2448,6 +2448,63 @@ def load_manifest(
2448
2448
  )
2449
2449
 
2450
2450
 
2451
+ def _checkout_prefix(abs_key: str, relative_keys: set[str]) -> str | None:
2452
+ """Longest directory prefix of ``abs_key`` whose suffix is in ``relative_keys``.
2453
+
2454
+ The suffix is forward-slash and NFC. ``src/c.py`` beats a shorter ``c.py``.
2455
+ Prefixes ``""``, ``"/"``, and ``"\\"`` are skipped so a shorter suffix can
2456
+ still match. The prefix that remains must be a real directory.
2457
+ """
2458
+ parts = _nfc(abs_key).replace("\\", "/").split("/")
2459
+ best: tuple[int, str] | None = None
2460
+ for i in range(1, len(parts)):
2461
+ suffix = "/".join(parts[i:])
2462
+ if suffix not in relative_keys:
2463
+ continue
2464
+ prefix = "/".join(parts[:i])
2465
+ if prefix in ("", "/", "\\"):
2466
+ continue
2467
+ if not Path(prefix).is_dir():
2468
+ continue
2469
+ if best is None or len(suffix) > best[0]:
2470
+ best = (len(suffix), prefix)
2471
+ return None if best is None else best[1]
2472
+
2473
+
2474
+ def _previous_checkout_absolute_keys(
2475
+ existing_keys: Iterable[Any],
2476
+ storage_root: Path | None,
2477
+ relative_keys: set[str],
2478
+ ) -> set[str]:
2479
+ """Absolute keys that still name a previous checkout (#3581).
2480
+
2481
+ A key is a candidate only when :func:`_to_relative_for_storage` keeps it
2482
+ absolute against ``storage_root`` (a sibling row that becomes relative,
2483
+ including #3785, is not a candidate). Candidates that share one directory
2484
+ prefix are a previous checkout when that group has at least two keys. One
2485
+ absolute key is an include row and stays. ``storage_root is None`` yields
2486
+ an empty set.
2487
+ """
2488
+ if storage_root is None:
2489
+ return set()
2490
+ groups: dict[str, set[str]] = {}
2491
+ for key in existing_keys:
2492
+ if not isinstance(key, str) or not _looks_absolute(key):
2493
+ continue
2494
+ stored = _nfc(_to_relative_for_storage(key, storage_root))
2495
+ if not _looks_absolute(stored):
2496
+ continue
2497
+ prefix = _checkout_prefix(stored, relative_keys)
2498
+ if prefix is None:
2499
+ continue
2500
+ groups.setdefault(prefix, set()).add(key)
2501
+ stale: set[str] = set()
2502
+ for keys in groups.values():
2503
+ if len(keys) >= 2:
2504
+ stale.update(keys)
2505
+ return stale
2506
+
2507
+
2451
2508
  def save_manifest(
2452
2509
  files: dict[str, list[str]],
2453
2510
  manifest_path: str = _MANIFEST_PATH,
@@ -2480,9 +2537,12 @@ def save_manifest(
2480
2537
  forever and masquerading as deletions in detect_incremental. It must be
2481
2538
  the RAW detect output, not a stamp-filtered subset — pruning to a
2482
2539
  filtered set would erase rows the filter merely omitted (failed chunks,
2483
- --code-only doc rows). Out-of-root entries are never pruned. Callers
2484
- saving a SUBSET of files (changed_paths hooks, skill runbooks, #917)
2485
- must leave this None so their untouched rows are preserved.
2540
+ --code-only doc rows). When this argument is set, two or more absolute
2541
+ keys that share a directory prefix and match relative keys this save writes
2542
+ are a previous checkout and are dropped (#3581). A single include row stays.
2543
+ Callers saving a SUBSET of files (changed_paths hooks, skill runbooks, #917)
2544
+ must leave this None so their untouched rows, including out-of-root rows,
2545
+ are preserved.
2486
2546
 
2487
2547
  ``clear_semantic`` (#1948): files that were dispatched this run but
2488
2548
  produced no stamped output (e.g. the LLM omitted their chunk on a
@@ -2583,6 +2643,21 @@ def save_manifest(
2583
2643
  # caller supplied the full scan corpus, additionally prune in-root rows
2584
2644
  # the scan no longer covers: those files were excluded, not deleted, and
2585
2645
  # keeping the row makes them look deleted on every future run (#1908).
2646
+ all_files = [f for file_list in files.values() for f in file_list]
2647
+ storage_root = _manifest_storage_anchor(manifest_path, root) if root is not None else None
2648
+ # A subset save omits scan_corpus and must keep every live row it was not
2649
+ # given (#917), including an include row and a previous checkout. The
2650
+ # checkout drop runs only on a full scan.
2651
+ stale_checkout: set[str] = set()
2652
+ if scan_set is not None and storage_root is not None:
2653
+ new_rels: set[str] = set()
2654
+ for f in all_files:
2655
+ stored = _nfc(_to_relative_for_storage(_nfc(f), storage_root))
2656
+ if not _looks_absolute(stored):
2657
+ new_rels.add(stored)
2658
+ stale_checkout = _previous_checkout_absolute_keys(
2659
+ existing.keys(), storage_root, new_rels
2660
+ )
2586
2661
  manifest: dict[str, dict] = {}
2587
2662
  for f, entry in existing.items():
2588
2663
  normalised = _normalise_entry(entry)
@@ -2593,6 +2668,8 @@ def save_manifest(
2593
2668
  continue
2594
2669
  except OSError:
2595
2670
  continue
2671
+ if f in stale_checkout:
2672
+ continue # previous checkout copied with graphify-out (#3581)
2596
2673
  if scan_set is not None and not _in_scan(f) and _in_root(f):
2597
2674
  continue # excluded-but-alive: drop the stale row (#1908)
2598
2675
  if clear_ast_set is not None and _in_clear_ast(f):
@@ -2605,7 +2682,6 @@ def save_manifest(
2605
2682
  normalised = {**normalised, "semantic_hash": ""}
2606
2683
  manifest[f] = normalised
2607
2684
 
2608
- all_files = [f for file_list in files.values() for f in file_list]
2609
2685
  with ThreadPoolExecutor() as pool:
2610
2686
  raw = pool.map(_stat_and_hash, all_files)
2611
2687
  hashed: dict[str, tuple[float, str]] = {
@@ -2646,7 +2722,6 @@ def save_manifest(
2646
2722
  "semantic_hash": sem_h,
2647
2723
  }
2648
2724
  manifest[key] = entry
2649
- storage_root = _manifest_storage_anchor(manifest_path, root) if root is not None else None
2650
2725
  if storage_root is not None:
2651
2726
  manifest = _collapse_manifest_duplicates(
2652
2727
  manifest.items(), lambda k: _nfc(_to_relative_for_storage(k, storage_root))