cg-code-graph 0.22.0__tar.gz → 0.23.1__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 (399) hide show
  1. {cg_code_graph-0.22.0/cg_code_graph.egg-info → cg_code_graph-0.23.1}/PKG-INFO +2 -2
  2. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/README.md +1 -1
  3. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/__init__.py +1 -1
  4. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/cli.py +30 -1
  5. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/coverage.py +13 -0
  6. cg_code_graph-0.23.1/cg_code_graph/install_rules.py +88 -0
  7. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/link.py +87 -3
  8. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_graphs.py +53 -10
  9. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_install.py +18 -1
  10. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_server.py +108 -28
  11. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nuxt/plugin.py +33 -2
  12. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/query.py +231 -5
  13. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1/cg_code_graph.egg-info}/PKG-INFO +2 -2
  14. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/SOURCES.txt +7 -0
  15. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_dart_isolates.py +15 -0
  16. cg_code_graph-0.23.1/tests/test_dead_wrappers.py +39 -0
  17. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_django_flutter.py +4 -1
  18. cg_code_graph-0.23.1/tests/test_install_rules.py +82 -0
  19. cg_code_graph-0.23.1/tests/test_link_origin.py +80 -0
  20. cg_code_graph-0.23.1/tests/test_mcp_instructions.py +35 -0
  21. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_mcp_multi_graph.py +67 -0
  22. cg_code_graph-0.23.1/tests/test_nuxt_side_dirs.py +76 -0
  23. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_php_http.py +2 -1
  24. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_process_runs.py +18 -0
  25. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_realtime_native.py +18 -0
  26. cg_code_graph-0.23.1/tests/test_route_specs.py +71 -0
  27. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift.py +11 -0
  28. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_nuxt.py +1 -1
  29. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/LICENSE +0 -0
  30. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/MANIFEST.in +0 -0
  31. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/__main__.py +0 -0
  32. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/affected.py +0 -0
  33. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/agent_rules.py +0 -0
  34. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/agents.py +0 -0
  35. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/aitools.py +0 -0
  36. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/android_ipc.py +0 -0
  37. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/apple_ipc.py +0 -0
  38. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/apps.py +0 -0
  39. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/blindspots.py +0 -0
  40. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/bridges.py +0 -0
  41. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/brokers.py +0 -0
  42. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/concepts.py +0 -0
  43. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/config.py +0 -0
  44. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/__init__.py +0 -0
  45. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/cache.py +0 -0
  46. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/detect.py +0 -0
  47. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/env.py +0 -0
  48. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/extractors.py +0 -0
  49. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/fsutil.py +0 -0
  50. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/generated.py +0 -0
  51. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/model.py +0 -0
  52. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/paths.py +0 -0
  53. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/plugin.py +0 -0
  54. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/redact.py +0 -0
  55. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/store.py +0 -0
  56. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/core/syntax_errors.py +0 -0
  57. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/dart_isolates.py +0 -0
  58. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/doctor.py +0 -0
  59. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/explore.py +0 -0
  60. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/external.py +0 -0
  61. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/graphql.py +0 -0
  62. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/guard_facts.py +0 -0
  63. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/hooks.py +0 -0
  64. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/indexer.py +0 -0
  65. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/insecure_transport.py +0 -0
  66. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/jobs.py +0 -0
  67. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/lint_async.py +0 -0
  68. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/local_ipc.py +0 -0
  69. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/local_sockets.py +0 -0
  70. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/parity.py +0 -0
  71. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/parity_structure.py +0 -0
  72. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/payload.py +0 -0
  73. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plans.py +0 -0
  74. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/platform_scan.py +0 -0
  75. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/platforms.py +0 -0
  76. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/__init__.py +0 -0
  77. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/__init__.py +0 -0
  78. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/content.py +0 -0
  79. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/plugin.py +0 -0
  80. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  81. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  82. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  83. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/__init__.py +0 -0
  84. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/bridges.py +0 -0
  85. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  86. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  87. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  88. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/http.py +0 -0
  89. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/models.py +0 -0
  90. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/plugin.py +0 -0
  91. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/program.py +0 -0
  92. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/__init__.py +0 -0
  93. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/extras.py +0 -0
  94. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/models.py +0 -0
  95. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/plugin.py +0 -0
  96. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/schemas.py +0 -0
  97. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/shapes.py +0 -0
  98. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/urls.py +0 -0
  99. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/express/__init__.py +0 -0
  100. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/express/plugin.py +0 -0
  101. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  102. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  103. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/__init__.py +0 -0
  104. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/exact.py +0 -0
  105. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/plugin.py +0 -0
  106. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  107. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/interop.py +0 -0
  108. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/spring.py +0 -0
  109. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  110. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  111. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  112. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  113. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  114. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  115. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  116. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  117. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/tests.py +0 -0
  118. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/values.py +0 -0
  119. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/__init__.py +0 -0
  120. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/gates.py +0 -0
  121. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/runner.py +0 -0
  122. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/scipread.py +0 -0
  123. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/ts.py +0 -0
  124. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nest/__init__.py +0 -0
  125. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nest/plugin.py +0 -0
  126. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  127. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  128. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  129. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/__init__.py +0 -0
  130. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/external.py +0 -0
  131. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  132. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  133. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  134. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/gating.py +0 -0
  135. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/http_client.py +0 -0
  136. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  137. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/plugin.py +0 -0
  138. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/strings.py +0 -0
  139. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/__init__.py +0 -0
  140. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/aitools.py +0 -0
  141. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/external.py +0 -0
  142. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/fields.py +0 -0
  143. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/plugin.py +0 -0
  144. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/refs.py +0 -0
  145. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/roots.py +0 -0
  146. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/socketio.py +0 -0
  147. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/subproc.py +0 -0
  148. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/tests.py +0 -0
  149. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/values.py +0 -0
  150. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  151. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  152. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/values.py +0 -0
  153. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/__init__.py +0 -0
  154. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/cargo.py +0 -0
  155. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/plugin.py +0 -0
  156. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/syntax.py +0 -0
  157. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/__init__.py +0 -0
  158. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/importer.py +0 -0
  159. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/scip.proto +0 -0
  160. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  161. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  162. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  163. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/__init__.py +0 -0
  164. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  165. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/exact.py +0 -0
  166. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  167. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/packages.py +0 -0
  168. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/plugin.py +0 -0
  169. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/__init__.py +0 -0
  170. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  171. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
  172. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  173. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  174. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  175. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  176. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/nav.py +0 -0
  177. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/plugin.py +0 -0
  178. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/react_router.py +0 -0
  179. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  180. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/common.py +0 -0
  181. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/data.py +0 -0
  182. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/__init__.py +0 -0
  183. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/c_cpp.yaml +0 -0
  184. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/common.yaml +0 -0
  185. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/dart.yaml +0 -0
  186. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/django-ninja.yaml +0 -0
  187. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/django.yaml +0 -0
  188. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  189. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/express.yaml +0 -0
  190. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/java.yaml +0 -0
  191. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/kotlin.yaml +0 -0
  192. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/laravel.yaml +0 -0
  193. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nest.yaml +0 -0
  194. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nextjs.yaml +0 -0
  195. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nuxt.yaml +0 -0
  196. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/php.yaml +0 -0
  197. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/python.yaml +0 -0
  198. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/react-router.yaml +0 -0
  199. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/rust.yaml +0 -0
  200. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/spring.yaml +0 -0
  201. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/swift.yaml +0 -0
  202. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/typescript.yaml +0 -0
  203. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/process_runs.py +0 -0
  204. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/__init__.py +0 -0
  205. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/builtin.py +0 -0
  206. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/matchers.py +0 -0
  207. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/view.py +0 -0
  208. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime.py +0 -0
  209. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_events.py +0 -0
  210. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_native.py +0 -0
  211. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_ws.py +0 -0
  212. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/roundtrip.py +0 -0
  213. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/routes.py +0 -0
  214. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/rpc.py +0 -0
  215. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/sdk_systems.py +0 -0
  216. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/sockets.py +0 -0
  217. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/ssrf_input.py +0 -0
  218. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/starters.py +0 -0
  219. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/surface.py +0 -0
  220. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/tests_index.py +0 -0
  221. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/udp_apps.py +0 -0
  222. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/__init__.py +0 -0
  223. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/graph.py +0 -0
  224. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/server.py +0 -0
  225. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/app.css +0 -0
  226. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/app.js +0 -0
  227. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/index.html +0 -0
  228. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/layered.js +0 -0
  229. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  230. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  231. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  232. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  233. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  234. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/package-lock.json +0 -0
  235. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/package.json +0 -0
  236. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  237. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/watch.py +0 -0
  238. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/webhook_subs.py +0 -0
  239. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/webhooks.py +0 -0
  240. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph/xcode.py +0 -0
  241. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  242. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/entry_points.txt +0 -0
  243. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/requires.txt +0 -0
  244. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/top_level.txt +0 -0
  245. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/pyproject.toml +0 -0
  246. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/setup.cfg +0 -0
  247. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_affected.py +0 -0
  248. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_agents_install.py +0 -0
  249. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_agents_md.py +0 -0
  250. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ai_tools.py +0 -0
  251. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_android_ipc.py +0 -0
  252. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_apple_ipc.py +0 -0
  253. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_astro.py +0 -0
  254. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_astro_content.py +0 -0
  255. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_astro_server.py +0 -0
  256. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_bridges.py +0 -0
  257. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_bridges_pigeon_monorepo.py +0 -0
  258. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_brokers.py +0 -0
  259. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_cache_clean.py +0 -0
  260. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_cache_invalidation.py +0 -0
  261. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_cache_migration.py +0 -0
  262. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_channels_tests.py +0 -0
  263. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_cli_output.py +0 -0
  264. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_completeness.py +0 -0
  265. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_config_extras.py +0 -0
  266. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_coverage.py +0 -0
  267. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_coverage_ts_hint.py +0 -0
  268. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_db_connections.py +0 -0
  269. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_dispatch_interfaces.py +0 -0
  270. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_docs_languages.py +0 -0
  271. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_docs_links.py +0 -0
  272. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_echo_ref.py +0 -0
  273. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_echo_wrapper.py +0 -0
  274. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_elysia.py +0 -0
  275. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_enum_constants.py +0 -0
  276. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_env.py +0 -0
  277. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_explore.py +0 -0
  278. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_external.py +0 -0
  279. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_fp_batch.py +0 -0
  280. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_gating.py +0 -0
  281. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_generated.py +0 -0
  282. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_graphql.py +0 -0
  283. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_hooks.py +0 -0
  284. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_impact_overrides.py +0 -0
  285. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_index_isolation.py +0 -0
  286. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_inherited_overrides.py +0 -0
  287. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_inline_guards.py +0 -0
  288. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_192.py +0 -0
  289. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_202.py +0 -0
  290. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_203.py +0 -0
  291. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_205.py +0 -0
  292. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_206.py +0 -0
  293. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_207.py +0 -0
  294. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_208.py +0 -0
  295. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_209.py +0 -0
  296. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_210.py +0 -0
  297. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_211.py +0 -0
  298. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_issue_211_used_at.py +0 -0
  299. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_java.py +0 -0
  300. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_java_exact.py +0 -0
  301. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_jobs.py +0 -0
  302. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_js_refs.py +0 -0
  303. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_js_runtime.py +0 -0
  304. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin.py +0 -0
  305. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_binding.py +0 -0
  306. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_exact.py +0 -0
  307. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_fields.py +0 -0
  308. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_mixed.py +0 -0
  309. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_nav_consts.py +0 -0
  310. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_kotlin_props.py +0 -0
  311. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_laravel_determinism.py +0 -0
  312. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_laravel_resources.py +0 -0
  313. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_lint_async.py +0 -0
  314. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_listing_files.py +0 -0
  315. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_local_ipc.py +0 -0
  316. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_local_sockets.py +0 -0
  317. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_mass_assignment.py +0 -0
  318. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_mcp.py +0 -0
  319. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_mcp_index.py +0 -0
  320. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_mcp_install.py +0 -0
  321. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_native_cfamily.py +0 -0
  322. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_native_concurrency.py +0 -0
  323. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_native_rust.py +0 -0
  324. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_nuxt_import_dirs.py +0 -0
  325. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_nuxt_rootsrc.py +0 -0
  326. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_packaging.py +0 -0
  327. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_parity.py +0 -0
  328. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_parity_structure.py +0 -0
  329. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_php_props.py +0 -0
  330. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_plain_js.py +0 -0
  331. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_plans.py +0 -0
  332. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_platform_gaps.py +0 -0
  333. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_platform_type_variants.py +0 -0
  334. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_platforms.py +0 -0
  335. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_platforms_apple.py +0 -0
  336. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_presets_config.py +0 -0
  337. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_process_ipc.py +0 -0
  338. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_protocols.py +0 -0
  339. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_app_tests_module.py +0 -0
  340. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_collection_chains.py +0 -0
  341. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_compat.py +0 -0
  342. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_entry_refs.py +0 -0
  343. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_fields.py +0 -0
  344. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_infer_cycles.py +0 -0
  345. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_roots.py +0 -0
  346. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_subprocess_tests.py +0 -0
  347. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_tests.py +0 -0
  348. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_web_hosts.py +0 -0
  349. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_web_routes.py +0 -0
  350. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_python_web_routes_more.py +0 -0
  351. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_react_router.py +0 -0
  352. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_readers_writers_specs.py +0 -0
  353. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_realtime.py +0 -0
  354. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_redact_salt.py +0 -0
  355. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_request_keys.py +0 -0
  356. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_roundtrip.py +0 -0
  357. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_route_tables.py +0 -0
  358. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_routes_search_explain.py +0 -0
  359. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_rpc.py +0 -0
  360. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_scip_health.py +0 -0
  361. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_sdk_external.py +0 -0
  362. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_sdk_external_infra.py +0 -0
  363. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_sdk_external_mail.py +0 -0
  364. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_snippet.py +0 -0
  365. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_sockets.py +0 -0
  366. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_spring.py +0 -0
  367. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ssrf.py +0 -0
  368. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_starters_budget.py +0 -0
  369. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_surface.py +0 -0
  370. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_surface_transport.py +0 -0
  371. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_binding.py +0 -0
  372. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_exact.py +0 -0
  373. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_facts.py +0 -0
  374. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_fields.py +0 -0
  375. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_modules.py +0 -0
  376. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_more.py +0 -0
  377. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_nav_values.py +0 -0
  378. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_parse_errors.py +0 -0
  379. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_props.py +0 -0
  380. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_sdk.py +0 -0
  381. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_testing.py +0 -0
  382. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_swift_values.py +0 -0
  383. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_tests_scope.py +0 -0
  384. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_fields.py +0 -0
  385. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_fields_js_vue.py +0 -0
  386. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_file_specs.py +0 -0
  387. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_frameworks.py +0 -0
  388. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_node_http.py +0 -0
  389. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_ts_src_tsconfig.py +0 -0
  390. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_unguarded.py +0 -0
  391. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_values.py +0 -0
  392. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_viz.py +0 -0
  393. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_vue_nav.py +0 -0
  394. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_watch.py +0 -0
  395. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_webhooks.py +0 -0
  396. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_webhooks_152.py +0 -0
  397. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_webhooks_152b.py +0 -0
  398. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_websockets.py +0 -0
  399. {cg_code_graph-0.22.0 → cg_code_graph-0.23.1}/tests/test_workspace_link.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.22.0
3
+ Version: 0.23.1
4
4
  Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
5
5
  Author: cyberchronos00
6
6
  License-Expression: MIT
@@ -48,7 +48,7 @@ For you and your AI agent (CLI + MCP). No LLM in the graph.
48
48
  ```bash
49
49
  pipx install cg-code-graph # or: uv tool install cg-code-graph
50
50
  cg index . --db out/graph.db # prints starter queries for your repo
51
- cg install --host cursor # or claude, codex, vscode, …: registers the MCP server
51
+ cg install --host cursor # or claude, codex, vscode, …: registers the MCP server and a "use cg first" agent rule
52
52
  cg reaches table:orders --db out/graph.db # any table, connection or config key
53
53
  ```
54
54
 
@@ -21,7 +21,7 @@ For you and your AI agent (CLI + MCP). No LLM in the graph.
21
21
  ```bash
22
22
  pipx install cg-code-graph # or: uv tool install cg-code-graph
23
23
  cg index . --db out/graph.db # prints starter queries for your repo
24
- cg install --host cursor # or claude, codex, vscode, …: registers the MCP server
24
+ cg install --host cursor # or claude, codex, vscode, …: registers the MCP server and a "use cg first" agent rule
25
25
  cg reaches table:orders --db out/graph.db # any table, connection or config key
26
26
  ```
27
27
 
@@ -1,2 +1,2 @@
1
1
  """code-graph: deterministic code knowledge graph (beta)."""
2
- __version__ = "0.22.0"
2
+ __version__ = "0.23.1"
@@ -73,6 +73,10 @@ def _add_install_parser(sub, uninstall: bool):
73
73
  p.add_argument("--uninstall", action="store_true", help="remove the entry instead of writing it")
74
74
  p.add_argument("--dry-run", action="store_true", help="print the exact changes and write nothing")
75
75
  p.add_argument("--yes", action="store_true", help="skip the confirmation prompt")
76
+ p.add_argument("--no-rules", dest="rules", action="store_false",
77
+ help=("leave AGENTS.md and .cursor/rules/cg.mdc alone" if uninstall else
78
+ "do not write the 'use cg first' agent rules (AGENTS.md section, .cursor/rules/cg.mdc); "
79
+ "project scope only"))
76
80
  if not uninstall:
77
81
  p.add_argument("--registry", action="store_true",
78
82
  help="global single entry: cg-mcp with no --db; graphs come from the registry")
@@ -520,7 +524,8 @@ def main(argv=None):
520
524
  return run_install(a.host, scope="global" if a.glob else "project", root=a.dir, db=a.db,
521
525
  tools=a.tools, portable=a.portable, remove=a.cmd == "uninstall" or a.uninstall,
522
526
  dry_run=a.dry_run, assume_yes=a.yes, registry=registry, migrate=migrate,
523
- apply=bool(getattr(a, "apply", False)), graphs=getattr(a, "graphs", None))
527
+ apply=bool(getattr(a, "apply", False)), graphs=getattr(a, "graphs", None),
528
+ rules=a.rules)
524
529
  if a.cmd == "hooks":
525
530
  from . import hooks as HK
526
531
  return HK.run(a.action, root=a.dir, db=a.db, dry_run=a.dry_run, assume_yes=a.yes)
@@ -636,6 +641,8 @@ def main(argv=None):
636
641
  print(json.dumps(res, indent=1, default=str) if a.json else render_protocols(res, max_items=a.max_items))
637
642
  return
638
643
  if a.cmd == "tests":
644
+ if _unknown_route(st, a.spec, a.json):
645
+ return
639
646
  res = Q.tests_covering(st, a.spec, min_conf=a.min_confidence, near_depth=a.max_depth or None,
640
647
  unit_only=a.unit_only, exclude_roots=a.exclude_root, through_roots=a.through_roots)
641
648
  res["completeness"] = _completeness(st, res.get("targets"))
@@ -674,12 +681,17 @@ def main(argv=None):
674
681
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_search(res))
675
682
  return
676
683
  if a.cmd == "reaches":
684
+ for spec in a.specs:
685
+ if _unknown_route(st, spec, a.json):
686
+ return
677
687
  res = Q.reaches(st, a.specs, min_conf=a.min_confidence, max_depth=a.max_depth, gate=None if a.gate == "none" else a.gate,
678
688
  platform=a.platform, connection=a.connection)
679
689
  res["completeness"] = _completeness(st, [x for t in res["targets"].values() for x in t] + [i["id"] for i in res["items"]])
680
690
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_reaches(res, show_paths=not a.no_paths))
681
691
  _note(res["completeness"], a.json)
682
692
  elif a.cmd == "impact":
693
+ if _unknown_route(st, a.spec, a.json):
694
+ return
683
695
  res = Q.impact(st, a.spec, min_conf=a.min_confidence, platform=a.platform)
684
696
  if a.json:
685
697
  res["completeness"] = _completeness(st, list(res["targets"]) + [c["id"] for c in res["callers"]])
@@ -755,6 +767,8 @@ def main(argv=None):
755
767
  res = Q.siblings(st, a.spec)
756
768
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_siblings(st, a.spec, res))
757
769
  elif a.cmd == "node":
770
+ if _unknown_route(st, a.spec, a.json):
771
+ return
758
772
  ids = list(dict.fromkeys(Q.resolve_targets(st, a.spec)))[:20]
759
773
  docs = [node_doc(st, nid) for nid in ids]
760
774
  if a.json:
@@ -774,10 +788,14 @@ def main(argv=None):
774
788
  if not p:
775
789
  raise SystemExit(1) # scripts can tell "no path" apart from a path
776
790
  elif a.cmd == "downstream":
791
+ if _unknown_route(st, a.spec, a.json):
792
+ return
777
793
  res = Q.downstream(st, a.spec, min_conf=a.min_confidence, max_depth=a.max_depth, gate=None if a.gate == "none" else a.gate,
778
794
  platform=a.platform)
779
795
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_downstream(res, show_paths=not a.no_paths))
780
796
  elif a.cmd == "api-calls":
797
+ if _unknown_route(st, a.spec, a.json):
798
+ return
781
799
  rows = Q.api_calls(st, a.spec)
782
800
  print(json.dumps(rows, indent=1, default=str) if a.json else Q.render_api_calls(rows))
783
801
  if not a.json:
@@ -789,6 +807,17 @@ def main(argv=None):
789
807
  doc = stats_doc(st)
790
808
  print(json.dumps(doc, indent=1, default=str) if a.json else render_stats(st, doc))
791
809
 
810
+ def _unknown_route(st, spec: str, as_json: bool) -> bool:
811
+ miss = Q.route_failure(st, spec)
812
+ if not miss:
813
+ return False
814
+ if as_json:
815
+ print(json.dumps({"error": miss["error"], "spec": miss["spec"], "suggestions": miss["suggestions"]}))
816
+ else:
817
+ print(miss["text"])
818
+ raise SystemExit(1)
819
+
820
+
792
821
  def node_doc(st, nid: str) -> dict:
793
822
  """One node with its attrs parsed and its outgoing / incoming edges (`cg node --json`, #75)."""
794
823
  n = dict(st.node(nid))
@@ -344,6 +344,9 @@ def compute(root: str | Path, plugins: dict, scip_imported: bool = False, report
344
344
  elif not e["files_complete"] and lang == "typescript" and e.get("unmapped"):
345
345
  e["hint"] = ("files outside the source dirs and test trees were not read: list the directories that hold "
346
346
  "source in .cg.yaml `include` (or a tsconfig.json `include`) and re-index")
347
+ if (nx := _nuxt_dirs(root)):
348
+ # Nuxt: name the dirs that were read, so a layer or module dir outside them is explained (#214)
349
+ e["hint"] = f"Nuxt project: the source dirs read are the srcDir plus server/ and shared/ ({nx}); " + e["hint"]
347
350
  se = (rep or {}).get("syntax_errors")
348
351
  if isinstance(se, list) and se and status not in ("skipped", "not_indexed"):
349
352
  # files parsed with syntax errors (#73): error spans and the declarations lost there
@@ -434,6 +437,16 @@ def _ts_not_run(root, with_php: bool) -> tuple[str, str]:
434
437
  return reason, hint
435
438
 
436
439
 
440
+ def _nuxt_dirs(root) -> str | None:
441
+ """'app/, server/, shared/' for a Nuxt project (the dirs the Nuxt plugin reads), else None."""
442
+ from .plugins.nuxt.plugin import _CFG_NAMES, find_src_dir, side_dirs
443
+ r = Path(root)
444
+ if not any((r / n).exists() for n in _CFG_NAMES):
445
+ return None
446
+ src = find_src_dir(r)
447
+ return ", ".join(["the project root" if src == "." else f"{src}/", *(f"{d}/" for d in side_dirs(r, src))])
448
+
449
+
437
450
  def _python_unmapped_hint(st: dict) -> str:
438
451
  if st.get("roots_mode") in ("configured", "flag"):
439
452
  where = "python.source_roots in .cg.yaml" if st["roots_mode"] == "configured" else "--python-root"
@@ -0,0 +1,88 @@
1
+ """Agent rules written by `cg install` (project scope, on by default, `--no-rules` skips): a short "use cg first"
2
+ section in AGENTS.md (Claude Code, Codex and other agents read it) and an alwaysApply Cursor rule at
3
+ .cursor/rules/cg.mdc. Only the `<!-- cg:start --> ... <!-- cg:end -->` section is ever written: a re-run replaces
4
+ it in place, content around it is kept, and `cg uninstall` removes it."""
5
+ from __future__ import annotations
6
+
7
+ import re
8
+ from pathlib import Path
9
+
10
+ START = "<!-- cg:start -->"
11
+ END = "<!-- cg:end -->"
12
+ AGENTS_FILE = "AGENTS.md"
13
+ CURSOR_FILE = ".cursor/rules/cg.mdc"
14
+ MDC_HEADER = "---\ndescription: Use the cg code graph before grep or opening whole files\nalwaysApply: true\n---\n"
15
+ _SECTION = re.compile(re.escape(START) + r".*?" + re.escape(END), re.S)
16
+
17
+
18
+ def body(db: str = "out/graph.db") -> str:
19
+ return (
20
+ "## Code graph (cg)\n\n"
21
+ "This repo has a cg code graph (MCP server `cg`). Use it before grep or opening whole files:\n"
22
+ "- `search` to find a symbol (file:line);\n"
23
+ "- `impact` before editing a function (or `reaches` for a table, column or env key) to see what the change affects;\n"
24
+ "- `snippet` to read one symbol instead of a whole file;\n"
25
+ "- `graphs` if unsure which graph to query.\n\n"
26
+ "Use normal search only for what cg reports as not covered (`coverage`). Without MCP: "
27
+ f"`cg search|impact|snippet <symbol> --db {db}`.\n")
28
+
29
+
30
+ def section(db: str = "out/graph.db") -> str:
31
+ return f"{START}\n{body(db)}{END}"
32
+
33
+
34
+ def _plan(path: Path, new: str | None, old: str, delete: bool = False) -> dict:
35
+ if delete:
36
+ return {"path": str(path), "kind": "text", "action": "remove", "old": old, "new": "", "delete_file": True}
37
+ if new == old:
38
+ return {"path": str(path), "kind": "text", "action": "noop", "old": old, "new": old, "current": True}
39
+ action = "insert" if not _SECTION.search(old) else ("remove" if not _SECTION.search(new) else "update")
40
+ return {"path": str(path), "kind": "text", "action": action, "old": old, "new": new}
41
+
42
+
43
+ def _with_section(old: str, sec: str) -> str:
44
+ if _SECTION.search(old):
45
+ return _SECTION.sub(lambda _m: sec, old, count=1)
46
+ if not old:
47
+ return sec + "\n"
48
+ return old + ("" if old.endswith("\n\n") else "\n" if old.endswith("\n") else "\n\n") + sec + "\n"
49
+
50
+
51
+ def _without_section(old: str) -> str:
52
+ m = _SECTION.search(old)
53
+ if not m:
54
+ return old
55
+ s, e = m.start(), m.end()
56
+ while e < len(old) and old[e] == "\n":
57
+ e += 1
58
+ while s > 0 and old[s - 1] == "\n":
59
+ s -= 1
60
+ head = old[:s]
61
+ return (head + "\n" + old[e:]) if head and old[e:] else (head + "\n" if head else old[e:])
62
+
63
+
64
+ def plans(root: Path, remove: bool = False, db: str = "out/graph.db") -> list[dict]:
65
+ """One text plan per rules file (the shape `cg agents` previews and `cg install` applies)."""
66
+ out = []
67
+ sec = section(db)
68
+ agents = root / AGENTS_FILE
69
+ old = agents.read_text(encoding="utf-8") if agents.exists() else ""
70
+ if remove:
71
+ rest = _without_section(old)
72
+ out.append(_plan(agents, None, old, delete=True) if _SECTION.search(old) and not rest.strip() else _plan(agents, rest, old))
73
+ else:
74
+ out.append(_plan(agents, _with_section(old, sec), old))
75
+ mdc = root / CURSOR_FILE
76
+ old = mdc.read_text(encoding="utf-8") if mdc.exists() else ""
77
+ if remove:
78
+ rest = _without_section(old)
79
+ if mdc.exists() and _SECTION.search(old) and rest.strip() in ("", MDC_HEADER.strip()):
80
+ out.append(_plan(mdc, None, old, delete=True))
81
+ else:
82
+ out.append(_plan(mdc, rest, old))
83
+ else:
84
+ new = _with_section(old, sec)
85
+ if not new.startswith("---\n"):
86
+ new = MDC_HEADER + new # an alwaysApply header, added once in front of whatever is there
87
+ out.append(_plan(mdc, new, old))
88
+ return [p for p in out if not (remove and p["action"] == "noop" and not p["old"])]
@@ -101,20 +101,73 @@ def _method_ok(cm: str, rm: str) -> bool:
101
101
  return cm in rms or "ANY" in rms or (cm == "HEAD" and "GET" in rms)
102
102
 
103
103
 
104
+ _BASE_SEG = re.compile(r"^(api|v\d+)$", re.I)
105
+
106
+
104
107
  def suffix_candidates(path: str, routes: list[dict]):
105
- """Origin unknown: align the client path with the END of route URIs (prefix assumed to be the base)."""
108
+ """Align the client path with the end of a route only when the dropped prefix is a base path (`api`, `v1`)."""
106
109
  cs = _segs(path)
107
110
  out = []
108
111
  for r in routes:
109
112
  us = _segs(r["uri"])
110
113
  if len(us) <= len(cs):
111
114
  continue
115
+ dropped = us[:len(us) - len(cs)]
116
+ if any(not _BASE_SEG.match(seg) for seg in dropped):
117
+ continue
112
118
  ok, info = match_path("/" + "/".join(cs), "/" + "/".join(us[len(us) - len(cs):]))
113
119
  if ok and info["lit"] > 0:
114
120
  out.append((r, "suffix", info))
115
121
  return out
116
122
 
117
123
 
124
+ def known_origin_text(attrs: dict) -> str | None:
125
+ """Env placeholder or literal base URL, when the client recorded one."""
126
+ kind = attrs.get("origin_kind")
127
+ origin = attrs.get("origin") or ""
128
+ base = attrs.get("base") or {}
129
+ if not isinstance(base, dict):
130
+ base = {}
131
+ parts = [origin, base.get("placeholder") or "", base.get("value") or ""]
132
+ text = " ".join(p for p in parts if isinstance(p, str) and p)
133
+ if kind == "env" or (isinstance(origin, str) and origin.startswith("{env.")):
134
+ return text or None
135
+ if kind == "other" or "://" in text:
136
+ return text or None
137
+ return None
138
+
139
+
140
+ _GENERIC_ORIGIN = {"env", "base", "url", "uri", "api", "app", "http", "https", "host", "origin", "endpoint", "service",
141
+ "internal", "server", "backend", "public", "private", "remote", "domain", "root", "prefix", "path",
142
+ "address", "addr", "runtime", "config", "runtimeconfig", "process", "import", "meta", "window",
143
+ "location", "nuxt", "next", "vite", "react", "expo", "vue", "localhost", "www", "com"}
144
+
145
+
146
+ def repos_for_origin(text: str, servers: list[str]) -> list[str] | None:
147
+ """Server names named by the origin.
148
+
149
+ ``None`` when the origin is a generic API base (``API_BASE_URL``) and does not name a repo:
150
+ matching stays as it was. ``[]`` when it names a service that is not one of ``servers``.
151
+ """
152
+ # camelCase splits (runtimeConfig.public.apiBase -> runtime config public api base); `-`, `_` and `.` all separate,
153
+ # so ORDERS_API_URL names an orders-api repo
154
+ split = re.sub(r"([a-z0-9])([A-Z])", r"\1 \2", text).lower()
155
+ norm = "-" + "-".join(re.findall(r"[a-z0-9]+", split)) + "-"
156
+ hits = []
157
+ for name in servers:
158
+ token = "-".join(re.findall(r"[a-z0-9]+", re.sub(r"([a-z0-9])([A-Z])", r"\1 \2", name).lower()))
159
+ if len(token) < 3:
160
+ continue
161
+ if f"-{token}-" in norm:
162
+ hits.append(name)
163
+ if hits:
164
+ return hits
165
+ tokens = [t for t in re.findall(r"[a-z][a-z0-9]+", split) if t not in _GENERIC_ORIGIN]
166
+ if not tokens:
167
+ return None
168
+ return []
169
+
170
+
118
171
  def match_endpoint(method: str, path: str, routes: list[dict], origin_kind: str = "api", origin: str | None = None,
119
172
  base_prefix: str | None = None) -> dict:
120
173
  """base_prefix: path part of a configured base URL already folded into `path` (http node attrs.base); when the
@@ -384,11 +437,24 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
384
437
  by_server[rt["server"]].append(rt)
385
438
  results = []
386
439
  new_edges = []
440
+ matched_origins: set[tuple[str, str]] = set()
387
441
  for client, ep_id, a, _test in http_rows:
388
442
  targets = [s for s in server_names if (s != client or folded_self) and (client not in allow or s in allow[client])]
389
443
  pool = [rt for s in targets for rt in by_server[s]]
390
444
  bp = base_path((a.get("base") or {}).get("value") or "") if a.get("base") else None
445
+ origin_text = known_origin_text(a)
446
+ owners = repos_for_origin(origin_text, targets) if origin_text else None
447
+ if owners is not None and len(owners) == 1:
448
+ pool = [rt for rt in pool if rt["server"] == owners[0]]
391
449
  res = match_endpoint(a["method"], a["path"], pool, a.get("origin_kind", "api"), a.get("origin"), base_prefix=bp or None)
450
+ if origin_text and owners == [] and not res.get("matched") and a.get("origin_kind") != "other":
451
+ reason = res.get("reason") or ""
452
+ if reason.startswith(("no backend route", "not a backend URL")) or "suffix" in reason:
453
+ res["_reason_before_external"] = reason
454
+ res["_origin_text"] = origin_text
455
+ res["reason"] = "external (other origin)"
456
+ elif origin_text and res.get("matched"):
457
+ matched_origins.add((client, origin_text))
392
458
  res.update({"endpoint": ep_id, "method": a["method"], "calls": calls_by_ep.get(ep_id, []),
393
459
  "_client": client, "_servers": targets})
394
460
  results.append(res)
@@ -397,6 +463,12 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
397
463
  rr = rmap[m["route"]]
398
464
  new_edges.append((ep_id, m["route"], "MATCHES_ROUTE", rr["file"], rr["line"], m["confidence"], CONFIDENCE_RANK[m["confidence"]],
399
465
  json.dumps({"client_path": a["path"], "uri_variant": m["uri_variant"], "segments": m["segments"]}), None))
466
+ for res in results:
467
+ # an origin whose other calls from this client matched a linked server is that backend, not an external one
468
+ before = res.pop("_reason_before_external", None)
469
+ if before is not None and (res["_client"], res.pop("_origin_text")) in matched_origins:
470
+ res["reason"] = before
471
+ res.pop("_origin_text", None)
400
472
  db.executemany("INSERT INTO edges(src,dst,kind,file,line,confidence,conf_rank,attrs,gate) VALUES (?,?,?,?,?,?,?,?,?)", new_edges)
401
473
  db.commit()
402
474
  subscriptions = pair_subscriber_urls(db, routes, server_names, allow, folded_self)
@@ -448,13 +520,20 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
448
520
  for sc in scen[:1]:
449
521
  db.executemany("INSERT INTO node_entry_live VALUES (?,?,?,?,?)", [(sc, *r) for r in tag_entries_rows(nodes, edges, prop, skip_gate=sc)])
450
522
  db.commit()
523
+ # call sites whose wrapper no entry point reaches are matched, but not live
524
+ live_ids = {r[0] for r in db.execute("SELECT DISTINCT node_id FROM node_entry WHERE entry_kind != 'test'")}
525
+ for r in results:
526
+ for c in r["calls"]:
527
+ c["live"] = c.get("src") in live_ids
528
+ if r["matched"] and r["calls"] and not any(c.get("live") for c in r["calls"]):
529
+ r["no_live_caller"] = True
451
530
  # ---- stats: per call site and per distinct endpoint
452
531
  n_ep = len(results)
453
532
  m_ep = sum(1 for r in results if r["matched"])
454
533
  site_match = {}
455
534
  for r in results:
456
535
  for c in r["calls"]:
457
- site_match[c["at"]] = site_match.get(c["at"], False) or bool(r["matched"])
536
+ site_match[c["at"]] = site_match.get(c["at"], False) or (bool(r["matched"]) and c.get("live", True))
458
537
  sites = list(site_match)
459
538
  m_sites = sum(1 for v in site_match.values() if v)
460
539
  conf_ct = defaultdict(int)
@@ -476,7 +555,7 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
476
555
  for r in eps:
477
556
  hit = any(rmap[m["route"]]["server"] == server for m in r["matched"])
478
557
  for c in r["calls"]:
479
- sm[c["at"]] = sm.get(c["at"], False) or hit
558
+ sm[c["at"]] = sm.get(c["at"], False) or (hit and c.get("live", True))
480
559
  pair_stats.append({"client": client, "server": server, "endpoints": len(eps),
481
560
  "endpoints_matched": sum(1 for r in eps if any(rmap[m["route"]]["server"] == server for m in r["matched"])),
482
561
  "call_sites": len(sm), "call_sites_matched": sum(1 for v in sm.values() if v)})
@@ -667,6 +746,11 @@ def write_match_report(res: dict, out_prefix: str) -> None:
667
746
  at = ", ".join(sorted({c["at"] for c in r["calls"]})[:3])
668
747
  extra = f" closest={r['closest']}" if r.get("closest") else (f" near={r['near']}" if r.get("near") else "")
669
748
  L.append(f"- `{r['endpoint']}` - {r['reason']}{extra} - at {at}")
749
+ dead = [r for r in res["results"] if r.get("no_live_caller")]
750
+ if dead:
751
+ L += ["", "## Matched, no live caller", ""]
752
+ for r in dead:
753
+ L.append(f"- `{r['endpoint']}` — matched, no live caller")
670
754
  L += ["", "## Ambiguous / heuristic matches", ""]
671
755
  for r in res["results"]:
672
756
  if r["matched"] and (len(r["matched"]) > 1 or any(m["confidence"] == "heuristic" for m in r["matched"])):
@@ -68,7 +68,7 @@ def git_head(root: Path) -> str | None:
68
68
 
69
69
 
70
70
  def _valid_name(name: str) -> bool:
71
- return bool(name) and all(c.isalnum() or c in "_.-" for c in name)
71
+ return bool(name) and all(c.isalnum() or c in "_.-+" for c in name) # `app+api`: a combined graph
72
72
 
73
73
 
74
74
  def parse_db_arg(text: str) -> tuple[str, Path]:
@@ -318,9 +318,58 @@ def _superset(hits: list[GraphEntry]) -> GraphEntry | None:
318
318
  return strict[0] if len(strict) == 1 else None
319
319
 
320
320
 
321
+ def _deepest_repo(hits: list[GraphEntry], texts: list[str]) -> Path | None:
322
+ """The repo containing the path: the deepest matching root, when that root is unique."""
323
+ containing: list[Path] = []
324
+ for entry in hits:
325
+ for root in entry.roots:
326
+ if not any(_under(root, text) for text in texts):
327
+ continue
328
+ try:
329
+ containing.append(root.expanduser().resolve())
330
+ except OSError:
331
+ containing.append(root)
332
+ if not containing:
333
+ return None
334
+ deepest: list[Path] = []
335
+ for root in containing:
336
+ if any(other != root and _under(root, str(other)) for other in containing):
337
+ continue
338
+ deepest.append(root)
339
+ unique = set(deepest)
340
+ if len(unique) != 1:
341
+ return None
342
+ return next(iter(unique))
343
+
344
+
345
+ def _own_graph(hits: list[GraphEntry], texts: list[str]) -> GraphEntry | None:
346
+ """The one match whose roots are exactly the repo that contains the path."""
347
+ repo = _deepest_repo(hits, texts)
348
+ if repo is None:
349
+ return None
350
+ own = [entry for entry in hits if _root_set(entry) == {repo}]
351
+ return own[0] if len(own) == 1 else None
352
+
353
+
354
+ def _pick(registry: Registry, hits: list[GraphEntry], texts: list[str]) -> GraphEntry:
355
+ """Superset, then the graph that is only that repo, then the configured default."""
356
+ chosen = _superset(hits)
357
+ if chosen is not None:
358
+ return chosen
359
+ chosen = _own_graph(hits, texts)
360
+ if chosen is not None:
361
+ return chosen
362
+ if registry.default:
363
+ by = registry.by_name()
364
+ default = by.get(registry.default)
365
+ if default is not None and default in hits:
366
+ return default
367
+ raise _choice_error(hits)
368
+
369
+
321
370
  def resolve(registry: Registry, *, graph: str | None, paths: list[str],
322
371
  cwd: Path | None = None, mcp_roots: list[str] | None = None) -> GraphEntry:
323
- """Pick a graph. Several matches stay an error unless one graph's roots contain the others."""
372
+ """Pick a graph. Several matches use a superset, then a single-repo graph, then the default."""
324
373
  by = registry.by_name()
325
374
  if graph:
326
375
  if graph not in by:
@@ -330,10 +379,7 @@ def resolve(registry: Registry, *, graph: str | None, paths: list[str],
330
379
  if len(path_hits) == 1:
331
380
  return path_hits[0]
332
381
  if len(path_hits) > 1:
333
- chosen = _superset(path_hits)
334
- if chosen is not None:
335
- return chosen
336
- raise _choice_error(path_hits)
382
+ return _pick(registry, path_hits, paths)
337
383
  places: list[str] = []
338
384
  if mcp_roots:
339
385
  places.extend(mcp_roots)
@@ -342,10 +388,7 @@ def resolve(registry: Registry, *, graph: str | None, paths: list[str],
342
388
  if len(loc_hits) == 1:
343
389
  return loc_hits[0]
344
390
  if len(loc_hits) > 1:
345
- chosen = _superset(loc_hits)
346
- if chosen is not None:
347
- return chosen
348
- raise _choice_error(loc_hits)
391
+ return _pick(registry, loc_hits, places)
349
392
  if registry.default and registry.default in by:
350
393
  return by[registry.default]
351
394
  if len(registry.entries) == 1:
@@ -781,6 +781,9 @@ def _apply_file(plan: dict) -> None:
781
781
  if path.exists():
782
782
  path.unlink()
783
783
  parent = path.parent
784
+ if parent.name == "rules" and parent.parent.name == ".cursor" and parent.exists() and not any(parent.iterdir()):
785
+ parent.rmdir() # .cursor/rules/cg.mdc was the only rule
786
+ parent = parent.parent
784
787
  if parent.name in _EMPTY_PARENTS and parent.exists() and not any(parent.iterdir()):
785
788
  parent.rmdir()
786
789
  return
@@ -1023,7 +1026,7 @@ def run(hosts: list[str] | None, *, scope: str, root: str = ".", db: str | None
1023
1026
  tools: str | None = None, portable: bool = False, remove: bool = False,
1024
1027
  dry_run: bool = False, assume_yes: bool = False, input_fn=input, out=print,
1025
1028
  registry: bool = False, migrate: bool = False, apply: bool = False,
1026
- graphs: str | None = None) -> int:
1029
+ graphs: str | None = None, rules: bool = True) -> int:
1027
1030
  if migrate:
1028
1031
  return run_migrate(hosts, scope=scope, root=root, tools=tools, graphs=graphs, apply=apply and not dry_run, out=out)
1029
1032
  rootp = Path(root).resolve()
@@ -1050,6 +1053,16 @@ def run(hosts: list[str] | None, *, scope: str, root: str = ".", db: str | None
1050
1053
  dbp = None
1051
1054
  plans = iter_plans(expanded, scope=scope, root=rootp, db=dbp, tools=tools, portable=portable, remove=remove,
1052
1055
  registry=registry)
1056
+ if rules and scope == "project" and not registry:
1057
+ # "use cg first" rules for agents: AGENTS.md section + alwaysApply Cursor rule (cg_code_graph/install_rules.py)
1058
+ from . import install_rules as IR
1059
+ shown = "out/graph.db"
1060
+ if dbp is not None and not portable:
1061
+ try:
1062
+ shown = dbp.relative_to(rootp).as_posix()
1063
+ except ValueError:
1064
+ shown = str(dbp)
1065
+ plans = [*plans, *IR.plans(rootp, remove=remove, db=shown)]
1053
1066
  if not portable and not remove and uses_module_fallback():
1054
1067
  out(_FALLBACK_NOTE)
1055
1068
  for plan in plans:
@@ -1088,6 +1101,10 @@ def run(hosts: list[str] | None, *, scope: str, root: str = ".", db: str | None
1088
1101
  _apply_file(plan)
1089
1102
  if plan.get("delete_file"):
1090
1103
  out(f"removed {plan['path']}")
1104
+ elif plan.get("kind") == "text" and plan["action"] == "remove":
1105
+ out(f"removed the cg section from {plan['path']}")
1106
+ elif plan.get("kind") == "text":
1107
+ out(f"wrote {plan['path']} (cg agent rules, {plan['action']})")
1091
1108
  else:
1092
1109
  out(f"wrote {plan['path']} ({plan['action']})")
1093
1110
  return 0