cg-code-graph 0.22.0__tar.gz → 0.23.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. {cg_code_graph-0.22.0/cg_code_graph.egg-info → cg_code_graph-0.23.0}/PKG-INFO +1 -1
  2. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/__init__.py +1 -1
  3. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/cli.py +24 -0
  4. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/link.py +70 -3
  5. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/mcp_graphs.py +53 -10
  6. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/mcp_server.py +72 -9
  7. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/query.py +231 -5
  8. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0/cg_code_graph.egg-info}/PKG-INFO +1 -1
  9. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph.egg-info/SOURCES.txt +3 -0
  10. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_dart_isolates.py +15 -0
  11. cg_code_graph-0.23.0/tests/test_dead_wrappers.py +39 -0
  12. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_django_flutter.py +4 -1
  13. cg_code_graph-0.23.0/tests/test_link_origin.py +39 -0
  14. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_mcp_multi_graph.py +67 -0
  15. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_php_http.py +2 -1
  16. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_process_runs.py +18 -0
  17. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_realtime_native.py +18 -0
  18. cg_code_graph-0.23.0/tests/test_route_specs.py +71 -0
  19. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift.py +11 -0
  20. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/LICENSE +0 -0
  21. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/MANIFEST.in +0 -0
  22. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/README.md +0 -0
  23. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/__main__.py +0 -0
  24. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/affected.py +0 -0
  25. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/agent_rules.py +0 -0
  26. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/agents.py +0 -0
  27. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/aitools.py +0 -0
  28. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/android_ipc.py +0 -0
  29. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/apple_ipc.py +0 -0
  30. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/apps.py +0 -0
  31. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/blindspots.py +0 -0
  32. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/bridges.py +0 -0
  33. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/brokers.py +0 -0
  34. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/concepts.py +0 -0
  35. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/config.py +0 -0
  36. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/__init__.py +0 -0
  37. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/cache.py +0 -0
  38. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/detect.py +0 -0
  39. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/env.py +0 -0
  40. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/extractors.py +0 -0
  41. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/fsutil.py +0 -0
  42. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/generated.py +0 -0
  43. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/model.py +0 -0
  44. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/paths.py +0 -0
  45. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/plugin.py +0 -0
  46. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/redact.py +0 -0
  47. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/store.py +0 -0
  48. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/core/syntax_errors.py +0 -0
  49. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/coverage.py +0 -0
  50. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/dart_isolates.py +0 -0
  51. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/doctor.py +0 -0
  52. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/explore.py +0 -0
  53. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/external.py +0 -0
  54. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/graphql.py +0 -0
  55. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/guard_facts.py +0 -0
  56. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/hooks.py +0 -0
  57. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/indexer.py +0 -0
  58. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/insecure_transport.py +0 -0
  59. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/jobs.py +0 -0
  60. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/lint_async.py +0 -0
  61. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/local_ipc.py +0 -0
  62. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/local_sockets.py +0 -0
  63. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/mcp_install.py +0 -0
  64. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/parity.py +0 -0
  65. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/parity_structure.py +0 -0
  66. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/payload.py +0 -0
  67. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plans.py +0 -0
  68. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/platform_scan.py +0 -0
  69. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/platforms.py +0 -0
  70. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/__init__.py +0 -0
  71. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/astro/__init__.py +0 -0
  72. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/astro/content.py +0 -0
  73. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/astro/plugin.py +0 -0
  74. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  75. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  76. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  77. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/__init__.py +0 -0
  78. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/bridges.py +0 -0
  79. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  80. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  81. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  82. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/http.py +0 -0
  83. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/models.py +0 -0
  84. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/plugin.py +0 -0
  85. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/dart/program.py +0 -0
  86. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/__init__.py +0 -0
  87. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/extras.py +0 -0
  88. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/models.py +0 -0
  89. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/plugin.py +0 -0
  90. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/schemas.py +0 -0
  91. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/shapes.py +0 -0
  92. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/django/urls.py +0 -0
  93. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/express/__init__.py +0 -0
  94. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/express/plugin.py +0 -0
  95. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  96. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  97. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/java/__init__.py +0 -0
  98. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/java/exact.py +0 -0
  99. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/java/plugin.py +0 -0
  100. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  101. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/jvm/interop.py +0 -0
  102. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/jvm/spring.py +0 -0
  103. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  104. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  105. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  106. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  107. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  108. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  109. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  110. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  111. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/tests.py +0 -0
  112. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/laravel/values.py +0 -0
  113. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/native/__init__.py +0 -0
  114. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/native/gates.py +0 -0
  115. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/native/runner.py +0 -0
  116. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/native/scipread.py +0 -0
  117. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/native/ts.py +0 -0
  118. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nest/__init__.py +0 -0
  119. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nest/plugin.py +0 -0
  120. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  121. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  122. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  123. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
  124. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/__init__.py +0 -0
  125. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/external.py +0 -0
  126. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  127. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  128. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  129. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/gating.py +0 -0
  130. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/http_client.py +0 -0
  131. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  132. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/plugin.py +0 -0
  133. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/php/strings.py +0 -0
  134. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/__init__.py +0 -0
  135. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/aitools.py +0 -0
  136. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/external.py +0 -0
  137. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/fields.py +0 -0
  138. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/plugin.py +0 -0
  139. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/refs.py +0 -0
  140. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/roots.py +0 -0
  141. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/socketio.py +0 -0
  142. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/subproc.py +0 -0
  143. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/tests.py +0 -0
  144. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/python/values.py +0 -0
  145. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  146. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  147. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/pyweb/values.py +0 -0
  148. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/rust/__init__.py +0 -0
  149. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/rust/cargo.py +0 -0
  150. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/rust/plugin.py +0 -0
  151. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/rust/syntax.py +0 -0
  152. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/scip/__init__.py +0 -0
  153. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/scip/importer.py +0 -0
  154. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/scip/scip.proto +0 -0
  155. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  156. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  157. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  158. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/__init__.py +0 -0
  159. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  160. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/exact.py +0 -0
  161. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  162. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/packages.py +0 -0
  163. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/swift/plugin.py +0 -0
  164. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/__init__.py +0 -0
  165. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  166. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
  167. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  168. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  169. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  170. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  171. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/nav.py +0 -0
  172. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/plugin.py +0 -0
  173. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/ts/react_router.py +0 -0
  174. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  175. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/tsweb/common.py +0 -0
  176. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/plugins/tsweb/data.py +0 -0
  177. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/__init__.py +0 -0
  178. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/c_cpp.yaml +0 -0
  179. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/common.yaml +0 -0
  180. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/dart.yaml +0 -0
  181. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/django-ninja.yaml +0 -0
  182. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/django.yaml +0 -0
  183. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  184. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/express.yaml +0 -0
  185. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/java.yaml +0 -0
  186. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/kotlin.yaml +0 -0
  187. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/laravel.yaml +0 -0
  188. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/nest.yaml +0 -0
  189. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/nextjs.yaml +0 -0
  190. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/nuxt.yaml +0 -0
  191. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/php.yaml +0 -0
  192. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/python.yaml +0 -0
  193. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/react-router.yaml +0 -0
  194. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/rust.yaml +0 -0
  195. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/spring.yaml +0 -0
  196. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/swift.yaml +0 -0
  197. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/presets/typescript.yaml +0 -0
  198. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/process_runs.py +0 -0
  199. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/protocols/__init__.py +0 -0
  200. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/protocols/builtin.py +0 -0
  201. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/protocols/matchers.py +0 -0
  202. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/protocols/view.py +0 -0
  203. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/realtime.py +0 -0
  204. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/realtime_events.py +0 -0
  205. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/realtime_native.py +0 -0
  206. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/realtime_ws.py +0 -0
  207. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/roundtrip.py +0 -0
  208. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/routes.py +0 -0
  209. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/rpc.py +0 -0
  210. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/sdk_systems.py +0 -0
  211. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/sockets.py +0 -0
  212. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/ssrf_input.py +0 -0
  213. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/starters.py +0 -0
  214. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/surface.py +0 -0
  215. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/tests_index.py +0 -0
  216. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/udp_apps.py +0 -0
  217. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/__init__.py +0 -0
  218. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/graph.py +0 -0
  219. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/server.py +0 -0
  220. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/app.css +0 -0
  221. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/app.js +0 -0
  222. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/index.html +0 -0
  223. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/layered.js +0 -0
  224. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  225. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  226. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  227. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  228. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  229. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/tools/package-lock.json +0 -0
  230. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/tools/package.json +0 -0
  231. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  232. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/watch.py +0 -0
  233. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/webhook_subs.py +0 -0
  234. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/webhooks.py +0 -0
  235. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph/xcode.py +0 -0
  236. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  237. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph.egg-info/entry_points.txt +0 -0
  238. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph.egg-info/requires.txt +0 -0
  239. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/cg_code_graph.egg-info/top_level.txt +0 -0
  240. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/pyproject.toml +0 -0
  241. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/setup.cfg +0 -0
  242. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_affected.py +0 -0
  243. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_agents_install.py +0 -0
  244. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_agents_md.py +0 -0
  245. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ai_tools.py +0 -0
  246. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_android_ipc.py +0 -0
  247. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_apple_ipc.py +0 -0
  248. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_astro.py +0 -0
  249. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_astro_content.py +0 -0
  250. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_astro_server.py +0 -0
  251. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_bridges.py +0 -0
  252. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_bridges_pigeon_monorepo.py +0 -0
  253. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_brokers.py +0 -0
  254. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_cache_clean.py +0 -0
  255. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_cache_invalidation.py +0 -0
  256. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_cache_migration.py +0 -0
  257. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_channels_tests.py +0 -0
  258. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_cli_output.py +0 -0
  259. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_completeness.py +0 -0
  260. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_config_extras.py +0 -0
  261. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_coverage.py +0 -0
  262. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_coverage_ts_hint.py +0 -0
  263. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_db_connections.py +0 -0
  264. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_dispatch_interfaces.py +0 -0
  265. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_docs_languages.py +0 -0
  266. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_docs_links.py +0 -0
  267. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_echo_ref.py +0 -0
  268. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_echo_wrapper.py +0 -0
  269. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_elysia.py +0 -0
  270. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_enum_constants.py +0 -0
  271. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_env.py +0 -0
  272. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_explore.py +0 -0
  273. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_external.py +0 -0
  274. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_fp_batch.py +0 -0
  275. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_gating.py +0 -0
  276. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_generated.py +0 -0
  277. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_graphql.py +0 -0
  278. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_hooks.py +0 -0
  279. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_impact_overrides.py +0 -0
  280. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_index_isolation.py +0 -0
  281. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_inherited_overrides.py +0 -0
  282. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_inline_guards.py +0 -0
  283. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_192.py +0 -0
  284. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_202.py +0 -0
  285. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_203.py +0 -0
  286. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_205.py +0 -0
  287. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_206.py +0 -0
  288. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_207.py +0 -0
  289. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_208.py +0 -0
  290. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_209.py +0 -0
  291. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_210.py +0 -0
  292. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_211.py +0 -0
  293. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_issue_211_used_at.py +0 -0
  294. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_java.py +0 -0
  295. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_java_exact.py +0 -0
  296. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_jobs.py +0 -0
  297. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_js_refs.py +0 -0
  298. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_js_runtime.py +0 -0
  299. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin.py +0 -0
  300. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_binding.py +0 -0
  301. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_exact.py +0 -0
  302. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_fields.py +0 -0
  303. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_mixed.py +0 -0
  304. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_nav_consts.py +0 -0
  305. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_kotlin_props.py +0 -0
  306. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_laravel_determinism.py +0 -0
  307. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_laravel_resources.py +0 -0
  308. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_lint_async.py +0 -0
  309. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_listing_files.py +0 -0
  310. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_local_ipc.py +0 -0
  311. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_local_sockets.py +0 -0
  312. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_mass_assignment.py +0 -0
  313. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_mcp.py +0 -0
  314. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_mcp_index.py +0 -0
  315. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_mcp_install.py +0 -0
  316. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_native_cfamily.py +0 -0
  317. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_native_concurrency.py +0 -0
  318. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_native_rust.py +0 -0
  319. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_nuxt_import_dirs.py +0 -0
  320. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_nuxt_rootsrc.py +0 -0
  321. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_packaging.py +0 -0
  322. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_parity.py +0 -0
  323. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_parity_structure.py +0 -0
  324. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_php_props.py +0 -0
  325. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_plain_js.py +0 -0
  326. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_plans.py +0 -0
  327. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_platform_gaps.py +0 -0
  328. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_platform_type_variants.py +0 -0
  329. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_platforms.py +0 -0
  330. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_platforms_apple.py +0 -0
  331. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_presets_config.py +0 -0
  332. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_process_ipc.py +0 -0
  333. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_protocols.py +0 -0
  334. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_app_tests_module.py +0 -0
  335. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_collection_chains.py +0 -0
  336. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_compat.py +0 -0
  337. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_entry_refs.py +0 -0
  338. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_fields.py +0 -0
  339. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_infer_cycles.py +0 -0
  340. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_roots.py +0 -0
  341. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_subprocess_tests.py +0 -0
  342. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_tests.py +0 -0
  343. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_web_hosts.py +0 -0
  344. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_web_routes.py +0 -0
  345. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_python_web_routes_more.py +0 -0
  346. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_react_router.py +0 -0
  347. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_readers_writers_specs.py +0 -0
  348. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_realtime.py +0 -0
  349. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_redact_salt.py +0 -0
  350. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_request_keys.py +0 -0
  351. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_roundtrip.py +0 -0
  352. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_route_tables.py +0 -0
  353. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_routes_search_explain.py +0 -0
  354. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_rpc.py +0 -0
  355. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_scip_health.py +0 -0
  356. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_sdk_external.py +0 -0
  357. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_sdk_external_infra.py +0 -0
  358. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_sdk_external_mail.py +0 -0
  359. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_snippet.py +0 -0
  360. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_sockets.py +0 -0
  361. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_spring.py +0 -0
  362. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ssrf.py +0 -0
  363. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_starters_budget.py +0 -0
  364. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_surface.py +0 -0
  365. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_surface_transport.py +0 -0
  366. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_binding.py +0 -0
  367. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_exact.py +0 -0
  368. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_facts.py +0 -0
  369. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_fields.py +0 -0
  370. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_modules.py +0 -0
  371. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_more.py +0 -0
  372. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_nav_values.py +0 -0
  373. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_parse_errors.py +0 -0
  374. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_props.py +0 -0
  375. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_sdk.py +0 -0
  376. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_testing.py +0 -0
  377. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_swift_values.py +0 -0
  378. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_tests_scope.py +0 -0
  379. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_fields.py +0 -0
  380. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_fields_js_vue.py +0 -0
  381. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_file_specs.py +0 -0
  382. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_frameworks.py +0 -0
  383. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_node_http.py +0 -0
  384. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_nuxt.py +0 -0
  385. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_ts_src_tsconfig.py +0 -0
  386. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_unguarded.py +0 -0
  387. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_values.py +0 -0
  388. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_viz.py +0 -0
  389. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_vue_nav.py +0 -0
  390. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_watch.py +0 -0
  391. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_webhooks.py +0 -0
  392. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_webhooks_152.py +0 -0
  393. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_webhooks_152b.py +0 -0
  394. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/tests/test_websockets.py +0 -0
  395. {cg_code_graph-0.22.0 → cg_code_graph-0.23.0}/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.0
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
@@ -1,2 +1,2 @@
1
1
  """code-graph: deterministic code knowledge graph (beta)."""
2
- __version__ = "0.22.0"
2
+ __version__ = "0.23.0"
@@ -636,6 +636,8 @@ def main(argv=None):
636
636
  print(json.dumps(res, indent=1, default=str) if a.json else render_protocols(res, max_items=a.max_items))
637
637
  return
638
638
  if a.cmd == "tests":
639
+ if _unknown_route(st, a.spec, a.json):
640
+ return
639
641
  res = Q.tests_covering(st, a.spec, min_conf=a.min_confidence, near_depth=a.max_depth or None,
640
642
  unit_only=a.unit_only, exclude_roots=a.exclude_root, through_roots=a.through_roots)
641
643
  res["completeness"] = _completeness(st, res.get("targets"))
@@ -674,12 +676,17 @@ def main(argv=None):
674
676
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_search(res))
675
677
  return
676
678
  if a.cmd == "reaches":
679
+ for spec in a.specs:
680
+ if _unknown_route(st, spec, a.json):
681
+ return
677
682
  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
683
  platform=a.platform, connection=a.connection)
679
684
  res["completeness"] = _completeness(st, [x for t in res["targets"].values() for x in t] + [i["id"] for i in res["items"]])
680
685
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_reaches(res, show_paths=not a.no_paths))
681
686
  _note(res["completeness"], a.json)
682
687
  elif a.cmd == "impact":
688
+ if _unknown_route(st, a.spec, a.json):
689
+ return
683
690
  res = Q.impact(st, a.spec, min_conf=a.min_confidence, platform=a.platform)
684
691
  if a.json:
685
692
  res["completeness"] = _completeness(st, list(res["targets"]) + [c["id"] for c in res["callers"]])
@@ -755,6 +762,8 @@ def main(argv=None):
755
762
  res = Q.siblings(st, a.spec)
756
763
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_siblings(st, a.spec, res))
757
764
  elif a.cmd == "node":
765
+ if _unknown_route(st, a.spec, a.json):
766
+ return
758
767
  ids = list(dict.fromkeys(Q.resolve_targets(st, a.spec)))[:20]
759
768
  docs = [node_doc(st, nid) for nid in ids]
760
769
  if a.json:
@@ -774,10 +783,14 @@ def main(argv=None):
774
783
  if not p:
775
784
  raise SystemExit(1) # scripts can tell "no path" apart from a path
776
785
  elif a.cmd == "downstream":
786
+ if _unknown_route(st, a.spec, a.json):
787
+ return
777
788
  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
789
  platform=a.platform)
779
790
  print(json.dumps(res, indent=1, default=str) if a.json else Q.render_downstream(res, show_paths=not a.no_paths))
780
791
  elif a.cmd == "api-calls":
792
+ if _unknown_route(st, a.spec, a.json):
793
+ return
781
794
  rows = Q.api_calls(st, a.spec)
782
795
  print(json.dumps(rows, indent=1, default=str) if a.json else Q.render_api_calls(rows))
783
796
  if not a.json:
@@ -789,6 +802,17 @@ def main(argv=None):
789
802
  doc = stats_doc(st)
790
803
  print(json.dumps(doc, indent=1, default=str) if a.json else render_stats(st, doc))
791
804
 
805
+ def _unknown_route(st, spec: str, as_json: bool) -> bool:
806
+ miss = Q.route_failure(st, spec)
807
+ if not miss:
808
+ return False
809
+ if as_json:
810
+ print(json.dumps({"error": miss["error"], "spec": miss["spec"], "suggestions": miss["suggestions"]}))
811
+ else:
812
+ print(miss["text"])
813
+ raise SystemExit(1)
814
+
815
+
792
816
  def node_doc(st, nid: str) -> dict:
793
817
  """One node with its attrs parsed and its outgoing / incoming edges (`cg node --json`, #75)."""
794
818
  n = dict(st.node(nid))
@@ -101,20 +101,67 @@ 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", "api", "app", "http", "https", "host", "origin", "endpoint", "service", "internal"}
141
+
142
+
143
+ def repos_for_origin(text: str, servers: list[str]) -> list[str] | None:
144
+ """Server names named by the origin.
145
+
146
+ ``None`` when the origin is a generic API base (``API_BASE_URL``) and does not name a repo:
147
+ matching stays as it was. ``[]`` when it names a service that is not one of ``servers``.
148
+ """
149
+ low = text.lower()
150
+ hits = []
151
+ for name in servers:
152
+ token = name.lower()
153
+ if len(token) < 3:
154
+ continue
155
+ if re.search(rf"(^|[^a-z0-9]){re.escape(token)}([^a-z0-9]|$)", low):
156
+ hits.append(name)
157
+ if hits:
158
+ return hits
159
+ tokens = [t for t in re.findall(r"[a-z][a-z0-9]+", low) if t not in _GENERIC_ORIGIN]
160
+ if not tokens:
161
+ return None
162
+ return []
163
+
164
+
118
165
  def match_endpoint(method: str, path: str, routes: list[dict], origin_kind: str = "api", origin: str | None = None,
119
166
  base_prefix: str | None = None) -> dict:
120
167
  """base_prefix: path part of a configured base URL already folded into `path` (http node attrs.base); when the
@@ -388,7 +435,15 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
388
435
  targets = [s for s in server_names if (s != client or folded_self) and (client not in allow or s in allow[client])]
389
436
  pool = [rt for s in targets for rt in by_server[s]]
390
437
  bp = base_path((a.get("base") or {}).get("value") or "") if a.get("base") else None
438
+ origin_text = known_origin_text(a)
439
+ owners = repos_for_origin(origin_text, targets) if origin_text else None
440
+ if owners is not None and len(owners) == 1:
441
+ pool = [rt for rt in pool if rt["server"] == owners[0]]
391
442
  res = match_endpoint(a["method"], a["path"], pool, a.get("origin_kind", "api"), a.get("origin"), base_prefix=bp or None)
443
+ if origin_text and owners == [] and not res.get("matched") and a.get("origin_kind") != "other":
444
+ reason = res.get("reason") or ""
445
+ if reason.startswith(("no backend route", "not a backend URL")) or "suffix" in reason:
446
+ res["reason"] = "external (other origin)"
392
447
  res.update({"endpoint": ep_id, "method": a["method"], "calls": calls_by_ep.get(ep_id, []),
393
448
  "_client": client, "_servers": targets})
394
449
  results.append(res)
@@ -448,13 +503,20 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
448
503
  for sc in scen[:1]:
449
504
  db.executemany("INSERT INTO node_entry_live VALUES (?,?,?,?,?)", [(sc, *r) for r in tag_entries_rows(nodes, edges, prop, skip_gate=sc)])
450
505
  db.commit()
506
+ # call sites whose wrapper no entry point reaches are matched, but not live
507
+ live_ids = {r[0] for r in db.execute("SELECT DISTINCT node_id FROM node_entry WHERE entry_kind != 'test'")}
508
+ for r in results:
509
+ for c in r["calls"]:
510
+ c["live"] = c.get("src") in live_ids
511
+ if r["matched"] and r["calls"] and not any(c.get("live") for c in r["calls"]):
512
+ r["no_live_caller"] = True
451
513
  # ---- stats: per call site and per distinct endpoint
452
514
  n_ep = len(results)
453
515
  m_ep = sum(1 for r in results if r["matched"])
454
516
  site_match = {}
455
517
  for r in results:
456
518
  for c in r["calls"]:
457
- site_match[c["at"]] = site_match.get(c["at"], False) or bool(r["matched"])
519
+ site_match[c["at"]] = site_match.get(c["at"], False) or (bool(r["matched"]) and c.get("live", True))
458
520
  sites = list(site_match)
459
521
  m_sites = sum(1 for v in site_match.values() if v)
460
522
  conf_ct = defaultdict(int)
@@ -476,7 +538,7 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
476
538
  for r in eps:
477
539
  hit = any(rmap[m["route"]]["server"] == server for m in r["matched"])
478
540
  for c in r["calls"]:
479
- sm[c["at"]] = sm.get(c["at"], False) or hit
541
+ sm[c["at"]] = sm.get(c["at"], False) or (hit and c.get("live", True))
480
542
  pair_stats.append({"client": client, "server": server, "endpoints": len(eps),
481
543
  "endpoints_matched": sum(1 for r in eps if any(rmap[m["route"]]["server"] == server for m in r["matched"])),
482
544
  "call_sites": len(sm), "call_sites_matched": sum(1 for v in sm.values() if v)})
@@ -667,6 +729,11 @@ def write_match_report(res: dict, out_prefix: str) -> None:
667
729
  at = ", ".join(sorted({c["at"] for c in r["calls"]})[:3])
668
730
  extra = f" closest={r['closest']}" if r.get("closest") else (f" near={r['near']}" if r.get("near") else "")
669
731
  L.append(f"- `{r['endpoint']}` - {r['reason']}{extra} - at {at}")
732
+ dead = [r for r in res["results"] if r.get("no_live_caller")]
733
+ if dead:
734
+ L += ["", "## Matched, no live caller", ""]
735
+ for r in dead:
736
+ L.append(f"- `{r['endpoint']}` — matched, no live caller")
670
737
  L += ["", "## Ambiguous / heuristic matches", ""]
671
738
  for r in res["results"]:
672
739
  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:
@@ -302,6 +302,11 @@ def _run_call(fn, args, kwargs) -> tuple[str, dict]:
302
302
  return str(ex), {"complete": False, "recorded": False, "languages": {}}
303
303
  _CALL.set({"graph_entry": entry, "graph_name": entry.name, "db": str(Path(entry.db).resolve())})
304
304
  named = entry.name
305
+ if entry.tools and str(entry.tools).strip():
306
+ allowed = set(selected_tool_names(entry.tools, warn=False))
307
+ if fn.__name__ not in allowed:
308
+ return (f"tool {fn.__name__} is not allowed for graph {entry.name}",
309
+ {"complete": False, "recorded": False, "languages": {}})
305
310
  token, ptoken, xtoken = _SCOPE.set(None), _PF.set(None), _EXTRA.set(None)
306
311
  try:
307
312
  try:
@@ -315,7 +320,7 @@ def _run_call(fn, args, kwargs) -> tuple[str, dict]:
315
320
  _SCOPE.reset(token)
316
321
  _PF.reset(ptoken)
317
322
  _EXTRA.reset(xtoken)
318
- if named and isinstance(txt, str) and not txt.startswith(("ambiguous graph:", "unknown graph ")):
323
+ if named and isinstance(txt, str) and not txt.startswith(("ambiguous graph:", "unknown graph ", "tool ")):
319
324
  txt = f"graph {named}\n" + txt
320
325
  comp = _completeness(scope)
321
326
  if pf:
@@ -481,6 +486,9 @@ def reaches(targets: list[str], min_confidence: str = "heuristic", group_by: str
481
486
  if pf and res["platform"].get("targets_not_built"):
482
487
  pline.append(f"not built for {pf}: {', '.join(short(t) for t in res['platform']['targets_not_built'][:6])}")
483
488
  if missing and len(missing) == len(res["targets"]):
489
+ route_lines = [Q.route_failure(st, s)["text"] for s in missing if Q.route_failure(st, s)]
490
+ if route_lines and len(route_lines) == len(missing):
491
+ return "\n".join(route_lines)
484
492
  return "\n".join(pline + [f"targets: {tl}"]) + f"\nno node matches {', '.join(map(repr, missing))}; try search() with part of the name (spec forms are listed in the server instructions)"
485
493
  if not items and connection:
486
494
  return "\n".join(pline + [f"targets: {tl}", f"no dependents recorded for {', '.join(res['targets'])} on connection {connection!r} "
@@ -558,6 +566,9 @@ def impact(method: str, min_confidence: str = "heuristic", max_items: int = 60,
558
566
  if Q.divergence_lists(st, pf, dropped):
559
567
  msg += f"; platform_divergence(target='{pf}') lists references to it that would not build"
560
568
  return "\n".join(pline + [msg])
569
+ miss = Q.route_failure(st, method)
570
+ if miss:
571
+ return miss["text"]
561
572
  return f"no method matches {method!r}; try search() with part of the name"
562
573
  _scope(list(r["targets"]) + [c["id"] for c in r["callers"]])
563
574
  if pf and set(r["platform"]["targets_not_built"]) == set(r["targets"]):
@@ -996,7 +1007,11 @@ def tests_covering(target: str, min_confidence: str = "heuristic", paths: bool =
996
1007
  classes, exclude_roots symbols; through_roots=true keeps them). UI / snapshot / screenshot tests (XCUITest,
997
1008
  Compose UI / Espresso, Playwright / Cypress, *UITests / androidTest folders) are listed apart, or left out
998
1009
  with unit_only=true. The summary line counts what was left out and why."""
999
- res = Q.tests_covering(_st(), target, min_conf=min_confidence, near_depth=max_depth or None, unit_only=unit_only,
1010
+ st = _st()
1011
+ miss = Q.route_failure(st, target)
1012
+ if miss:
1013
+ return miss["text"]
1014
+ res = Q.tests_covering(st, target, min_conf=min_confidence, near_depth=max_depth or None, unit_only=unit_only,
1000
1015
  exclude_roots=exclude_roots, through_roots=through_roots)
1001
1016
  _scope(res.get("targets") or [])
1002
1017
  return Q.render_tests_covering(res, show_paths=paths)
@@ -1239,6 +1254,9 @@ def downstream(target: str, max_per_kind: int = 25, paths: bool = True, min_conf
1239
1254
  pf, pline = _platform(st, platform)
1240
1255
  r = Q.downstream(st, target, min_conf=min_confidence, platform=pf)
1241
1256
  if not r["targets"]:
1257
+ miss = Q.route_failure(st, target)
1258
+ if miss:
1259
+ return miss["text"]
1242
1260
  return f"no node matches {target!r}; try search()"
1243
1261
  out = pline + [f"targets: {', '.join(short(t) for t in r['targets'][:4])} | reached {r['reached']} nodes | gate={r.get('gate')}"]
1244
1262
  if not r["sinks"]:
@@ -1328,8 +1346,14 @@ def api_calls(filter: str = "all", max_items: int = 60) -> str:
1328
1346
  """Frontend HTTP calls (method + path template) with call sites, request keys and the matched backend
1329
1347
  route + controller (combined graph). filter: all | unmatched | any substring (endpoint, route, caller, file) |
1330
1348
  a `*` glob (`GET /v1/*/orders*`, `*/staff/*`, `*useOrders*`) on the endpoint, its path, route, controller,
1331
- caller or call-site file."""
1349
+ caller or call-site file. `route:VERB /path` is an exact route match (verb case-insensitive; `:id`, `{id}` and
1350
+ `{order}` match one param segment). `route:POST /payments/*` or `route:* /payments` widens it. An unknown
1351
+ route returns `no such route` and the nearest routes. A call site with no entry point is marked
1352
+ `(no live caller)` and `filter='dead'` lists matched endpoints with no live call site."""
1332
1353
  st = _st()
1354
+ miss = Q.route_failure(st, filter)
1355
+ if miss:
1356
+ return miss["text"]
1333
1357
  rows = Q.api_calls(st, filter)
1334
1358
  gaps = defaultdict(list)
1335
1359
  for g in Q.forwarding_gaps(st):
@@ -1618,12 +1642,12 @@ def _tool_names() -> list[str]:
1618
1642
  return [t.name for t in server._tool_manager.list_tools()]
1619
1643
 
1620
1644
 
1621
- def apply_tool_allowlist(spec: str) -> list[str]:
1622
- """Keep only the tools selected by spec and return their names.
1645
+ def selected_tool_names(spec: str, *, warn: bool = True) -> list[str]:
1646
+ """Names selected by a tool spec, in server order. Does not change the listed set.
1623
1647
 
1624
1648
  Items are comma- or space-separated. `all` is every tool, `core` is the reading set,
1625
1649
  a name or fnmatch glob adds tools, and a leading `-` removes them (`all,-plan_*`).
1626
- Unknown names are warned once on stderr and ignored. An empty selection exits 2.
1650
+ Unknown names are warned once on stderr and ignored.
1627
1651
  """
1628
1652
  import fnmatch
1629
1653
  names = _tool_names()
@@ -1652,18 +1676,52 @@ def apply_tool_allowlist(spec: str) -> list[str]:
1652
1676
  selected -= matched
1653
1677
  else:
1654
1678
  selected |= matched
1655
- if unknown:
1679
+ if warn and unknown:
1656
1680
  print("cg-mcp: CG_MCP_TOOLS: unknown name(s): " + ", ".join(unknown), file=sys.stderr)
1657
- kept = [n for n in names if n in selected]
1681
+ return [n for n in names if n in selected]
1682
+
1683
+
1684
+ def registry_tool_spec(registry) -> str | None:
1685
+ """Union of per-graph allowlists. ``None`` means at least one graph lists every tool."""
1686
+ specs = [e.tools for e in registry.entries if e.tools and str(e.tools).strip()]
1687
+ if len(specs) != len(registry.entries):
1688
+ return None
1689
+ names: list[str] = []
1690
+ seen: set[str] = set()
1691
+ for spec in specs:
1692
+ for name in selected_tool_names(spec, warn=False):
1693
+ if name not in seen:
1694
+ seen.add(name)
1695
+ names.append(name)
1696
+ return ",".join(names) if names else None
1697
+
1698
+
1699
+ def apply_tool_allowlist(spec: str) -> list[str]:
1700
+ """Keep only the tools selected by spec and return their names.
1701
+
1702
+ An empty selection exits 2.
1703
+ """
1704
+ kept = selected_tool_names(spec)
1658
1705
  if not kept:
1659
1706
  print("cg-mcp: CG_MCP_TOOLS selects no tools", file=sys.stderr)
1660
1707
  raise SystemExit(2)
1661
- for name in names:
1708
+ selected = set(kept)
1709
+ for name in _tool_names():
1662
1710
  if name not in selected:
1663
1711
  server.remove_tool(name)
1664
1712
  return kept
1665
1713
 
1666
1714
 
1715
+ def apply_registry_tools(registry, server_tools: str | None = None) -> list[str] | None:
1716
+ """List one fixed set: ``server_tools`` when given, otherwise the union of per-graph allowlists."""
1717
+ if server_tools:
1718
+ return apply_tool_allowlist(server_tools)
1719
+ spec = registry_tool_spec(registry)
1720
+ if spec is None:
1721
+ return None
1722
+ return apply_tool_allowlist(spec)
1723
+
1724
+
1667
1725
  def expose_graph_argument() -> None:
1668
1726
  """Add optional `graph` to every tool schema. Single-`--db` mode leaves the schemas unchanged."""
1669
1727
  if STATE.get("graph_arg"):
@@ -1700,6 +1758,8 @@ def configure(*, dbs: list[str] | None = None, db_dir: str | None = None, graphs
1700
1758
  STATE["registry"] = reg
1701
1759
  STATE["db"] = str(Path(reg.entries[0].db).resolve())
1702
1760
  expose_graph_argument()
1761
+ if not STATE.get("server_tools"):
1762
+ apply_registry_tools(reg)
1703
1763
 
1704
1764
 
1705
1765
  def _install_roots_hook() -> None:
@@ -1771,8 +1831,11 @@ def main(argv=None):
1771
1831
  STATE["registry"] = reg
1772
1832
  STATE["db"] = str(Path(reg.entries[0].db).resolve())
1773
1833
  expose_graph_argument()
1834
+ STATE["server_tools"] = a.tools or None
1774
1835
  if a.tools:
1775
1836
  apply_tool_allowlist(a.tools)
1837
+ elif STATE.get("multi"):
1838
+ apply_registry_tools(STATE["registry"])
1776
1839
  server.run("stdio")
1777
1840
 
1778
1841