cg-code-graph 0.23.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 (400) hide show
  1. {cg_code_graph-0.23.0/cg_code_graph.egg-info → cg_code_graph-0.23.1}/PKG-INFO +2 -2
  2. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/README.md +1 -1
  3. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/__init__.py +1 -1
  4. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/cli.py +6 -1
  5. {cg_code_graph-0.23.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.23.0 → cg_code_graph-0.23.1}/cg_code_graph/link.py +22 -5
  8. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_install.py +18 -1
  9. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_server.py +36 -19
  10. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nuxt/plugin.py +33 -2
  11. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1/cg_code_graph.egg-info}/PKG-INFO +2 -2
  12. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/SOURCES.txt +4 -0
  13. cg_code_graph-0.23.1/tests/test_install_rules.py +82 -0
  14. cg_code_graph-0.23.1/tests/test_link_origin.py +80 -0
  15. cg_code_graph-0.23.1/tests/test_mcp_instructions.py +35 -0
  16. cg_code_graph-0.23.1/tests/test_nuxt_side_dirs.py +76 -0
  17. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_nuxt.py +1 -1
  18. cg_code_graph-0.23.0/tests/test_link_origin.py +0 -39
  19. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/LICENSE +0 -0
  20. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/MANIFEST.in +0 -0
  21. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/__main__.py +0 -0
  22. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/affected.py +0 -0
  23. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/agent_rules.py +0 -0
  24. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/agents.py +0 -0
  25. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/aitools.py +0 -0
  26. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/android_ipc.py +0 -0
  27. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/apple_ipc.py +0 -0
  28. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/apps.py +0 -0
  29. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/blindspots.py +0 -0
  30. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/bridges.py +0 -0
  31. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/brokers.py +0 -0
  32. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/concepts.py +0 -0
  33. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/config.py +0 -0
  34. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/__init__.py +0 -0
  35. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/cache.py +0 -0
  36. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/detect.py +0 -0
  37. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/env.py +0 -0
  38. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/extractors.py +0 -0
  39. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/fsutil.py +0 -0
  40. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/generated.py +0 -0
  41. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/model.py +0 -0
  42. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/paths.py +0 -0
  43. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/plugin.py +0 -0
  44. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/redact.py +0 -0
  45. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/store.py +0 -0
  46. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/core/syntax_errors.py +0 -0
  47. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/dart_isolates.py +0 -0
  48. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/doctor.py +0 -0
  49. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/explore.py +0 -0
  50. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/external.py +0 -0
  51. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/graphql.py +0 -0
  52. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/guard_facts.py +0 -0
  53. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/hooks.py +0 -0
  54. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/indexer.py +0 -0
  55. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/insecure_transport.py +0 -0
  56. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/jobs.py +0 -0
  57. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/lint_async.py +0 -0
  58. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/local_ipc.py +0 -0
  59. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/local_sockets.py +0 -0
  60. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/mcp_graphs.py +0 -0
  61. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/parity.py +0 -0
  62. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/parity_structure.py +0 -0
  63. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/payload.py +0 -0
  64. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plans.py +0 -0
  65. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/platform_scan.py +0 -0
  66. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/platforms.py +0 -0
  67. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/__init__.py +0 -0
  68. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/__init__.py +0 -0
  69. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/content.py +0 -0
  70. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/astro/plugin.py +0 -0
  71. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  72. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  73. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  74. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/__init__.py +0 -0
  75. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/bridges.py +0 -0
  76. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  77. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  78. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  79. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/http.py +0 -0
  80. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/models.py +0 -0
  81. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/plugin.py +0 -0
  82. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/dart/program.py +0 -0
  83. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/__init__.py +0 -0
  84. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/extras.py +0 -0
  85. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/models.py +0 -0
  86. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/plugin.py +0 -0
  87. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/schemas.py +0 -0
  88. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/shapes.py +0 -0
  89. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/django/urls.py +0 -0
  90. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/express/__init__.py +0 -0
  91. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/express/plugin.py +0 -0
  92. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  93. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  94. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/__init__.py +0 -0
  95. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/exact.py +0 -0
  96. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/java/plugin.py +0 -0
  97. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  98. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/interop.py +0 -0
  99. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/jvm/spring.py +0 -0
  100. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  101. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  102. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  103. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  104. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  105. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  106. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  107. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  108. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/tests.py +0 -0
  109. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/laravel/values.py +0 -0
  110. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/__init__.py +0 -0
  111. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/gates.py +0 -0
  112. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/runner.py +0 -0
  113. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/scipread.py +0 -0
  114. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/native/ts.py +0 -0
  115. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nest/__init__.py +0 -0
  116. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nest/plugin.py +0 -0
  117. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  118. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  119. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  120. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/__init__.py +0 -0
  121. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/external.py +0 -0
  122. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  123. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  124. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  125. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/gating.py +0 -0
  126. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/http_client.py +0 -0
  127. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  128. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/plugin.py +0 -0
  129. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/php/strings.py +0 -0
  130. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/__init__.py +0 -0
  131. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/aitools.py +0 -0
  132. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/external.py +0 -0
  133. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/fields.py +0 -0
  134. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/plugin.py +0 -0
  135. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/refs.py +0 -0
  136. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/roots.py +0 -0
  137. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/socketio.py +0 -0
  138. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/subproc.py +0 -0
  139. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/tests.py +0 -0
  140. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/python/values.py +0 -0
  141. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  142. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  143. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/pyweb/values.py +0 -0
  144. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/__init__.py +0 -0
  145. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/cargo.py +0 -0
  146. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/plugin.py +0 -0
  147. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/rust/syntax.py +0 -0
  148. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/__init__.py +0 -0
  149. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/importer.py +0 -0
  150. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/scip.proto +0 -0
  151. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  152. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  153. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  154. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/__init__.py +0 -0
  155. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  156. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/exact.py +0 -0
  157. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  158. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/packages.py +0 -0
  159. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/swift/plugin.py +0 -0
  160. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/__init__.py +0 -0
  161. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  162. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
  163. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  164. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  165. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  166. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  167. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/nav.py +0 -0
  168. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/plugin.py +0 -0
  169. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/ts/react_router.py +0 -0
  170. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  171. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/common.py +0 -0
  172. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/plugins/tsweb/data.py +0 -0
  173. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/__init__.py +0 -0
  174. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/c_cpp.yaml +0 -0
  175. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/common.yaml +0 -0
  176. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/dart.yaml +0 -0
  177. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/django-ninja.yaml +0 -0
  178. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/django.yaml +0 -0
  179. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  180. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/express.yaml +0 -0
  181. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/java.yaml +0 -0
  182. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/kotlin.yaml +0 -0
  183. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/laravel.yaml +0 -0
  184. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nest.yaml +0 -0
  185. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nextjs.yaml +0 -0
  186. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/nuxt.yaml +0 -0
  187. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/php.yaml +0 -0
  188. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/python.yaml +0 -0
  189. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/react-router.yaml +0 -0
  190. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/rust.yaml +0 -0
  191. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/spring.yaml +0 -0
  192. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/swift.yaml +0 -0
  193. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/presets/typescript.yaml +0 -0
  194. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/process_runs.py +0 -0
  195. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/__init__.py +0 -0
  196. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/builtin.py +0 -0
  197. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/matchers.py +0 -0
  198. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/protocols/view.py +0 -0
  199. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/query.py +0 -0
  200. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime.py +0 -0
  201. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_events.py +0 -0
  202. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_native.py +0 -0
  203. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/realtime_ws.py +0 -0
  204. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/roundtrip.py +0 -0
  205. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/routes.py +0 -0
  206. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/rpc.py +0 -0
  207. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/sdk_systems.py +0 -0
  208. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/sockets.py +0 -0
  209. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/ssrf_input.py +0 -0
  210. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/starters.py +0 -0
  211. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/surface.py +0 -0
  212. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/tests_index.py +0 -0
  213. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/udp_apps.py +0 -0
  214. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/__init__.py +0 -0
  215. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/graph.py +0 -0
  216. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/server.py +0 -0
  217. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/app.css +0 -0
  218. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/app.js +0 -0
  219. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/index.html +0 -0
  220. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/layered.js +0 -0
  221. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  222. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  223. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  224. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  225. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  226. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/package-lock.json +0 -0
  227. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/package.json +0 -0
  228. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  229. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/watch.py +0 -0
  230. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/webhook_subs.py +0 -0
  231. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/webhooks.py +0 -0
  232. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph/xcode.py +0 -0
  233. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  234. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/entry_points.txt +0 -0
  235. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/requires.txt +0 -0
  236. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/cg_code_graph.egg-info/top_level.txt +0 -0
  237. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/pyproject.toml +0 -0
  238. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/setup.cfg +0 -0
  239. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_affected.py +0 -0
  240. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_agents_install.py +0 -0
  241. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_agents_md.py +0 -0
  242. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ai_tools.py +0 -0
  243. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_android_ipc.py +0 -0
  244. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_apple_ipc.py +0 -0
  245. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_astro.py +0 -0
  246. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_astro_content.py +0 -0
  247. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_astro_server.py +0 -0
  248. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_bridges.py +0 -0
  249. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_bridges_pigeon_monorepo.py +0 -0
  250. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_brokers.py +0 -0
  251. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_cache_clean.py +0 -0
  252. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_cache_invalidation.py +0 -0
  253. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_cache_migration.py +0 -0
  254. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_channels_tests.py +0 -0
  255. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_cli_output.py +0 -0
  256. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_completeness.py +0 -0
  257. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_config_extras.py +0 -0
  258. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_coverage.py +0 -0
  259. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_coverage_ts_hint.py +0 -0
  260. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_dart_isolates.py +0 -0
  261. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_db_connections.py +0 -0
  262. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_dead_wrappers.py +0 -0
  263. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_dispatch_interfaces.py +0 -0
  264. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_django_flutter.py +0 -0
  265. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_docs_languages.py +0 -0
  266. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_docs_links.py +0 -0
  267. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_echo_ref.py +0 -0
  268. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_echo_wrapper.py +0 -0
  269. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_elysia.py +0 -0
  270. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_enum_constants.py +0 -0
  271. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_env.py +0 -0
  272. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_explore.py +0 -0
  273. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_external.py +0 -0
  274. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_fp_batch.py +0 -0
  275. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_gating.py +0 -0
  276. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_generated.py +0 -0
  277. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_graphql.py +0 -0
  278. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_hooks.py +0 -0
  279. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_impact_overrides.py +0 -0
  280. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_index_isolation.py +0 -0
  281. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_inherited_overrides.py +0 -0
  282. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_inline_guards.py +0 -0
  283. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_192.py +0 -0
  284. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_202.py +0 -0
  285. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_203.py +0 -0
  286. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_205.py +0 -0
  287. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_206.py +0 -0
  288. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_207.py +0 -0
  289. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_208.py +0 -0
  290. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_209.py +0 -0
  291. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_210.py +0 -0
  292. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_211.py +0 -0
  293. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_issue_211_used_at.py +0 -0
  294. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_java.py +0 -0
  295. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_java_exact.py +0 -0
  296. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_jobs.py +0 -0
  297. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_js_refs.py +0 -0
  298. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_js_runtime.py +0 -0
  299. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin.py +0 -0
  300. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_binding.py +0 -0
  301. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_exact.py +0 -0
  302. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_fields.py +0 -0
  303. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_mixed.py +0 -0
  304. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_nav_consts.py +0 -0
  305. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_kotlin_props.py +0 -0
  306. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_laravel_determinism.py +0 -0
  307. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_laravel_resources.py +0 -0
  308. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_lint_async.py +0 -0
  309. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_listing_files.py +0 -0
  310. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_local_ipc.py +0 -0
  311. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_local_sockets.py +0 -0
  312. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_mass_assignment.py +0 -0
  313. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_mcp.py +0 -0
  314. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_mcp_index.py +0 -0
  315. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_mcp_install.py +0 -0
  316. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_mcp_multi_graph.py +0 -0
  317. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_native_cfamily.py +0 -0
  318. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_native_concurrency.py +0 -0
  319. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_native_rust.py +0 -0
  320. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_nuxt_import_dirs.py +0 -0
  321. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_nuxt_rootsrc.py +0 -0
  322. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_packaging.py +0 -0
  323. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_parity.py +0 -0
  324. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_parity_structure.py +0 -0
  325. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_php_http.py +0 -0
  326. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_php_props.py +0 -0
  327. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_plain_js.py +0 -0
  328. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_plans.py +0 -0
  329. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_platform_gaps.py +0 -0
  330. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_platform_type_variants.py +0 -0
  331. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_platforms.py +0 -0
  332. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_platforms_apple.py +0 -0
  333. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_presets_config.py +0 -0
  334. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_process_ipc.py +0 -0
  335. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_process_runs.py +0 -0
  336. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_protocols.py +0 -0
  337. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_app_tests_module.py +0 -0
  338. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_collection_chains.py +0 -0
  339. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_compat.py +0 -0
  340. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_entry_refs.py +0 -0
  341. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_fields.py +0 -0
  342. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_infer_cycles.py +0 -0
  343. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_roots.py +0 -0
  344. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_subprocess_tests.py +0 -0
  345. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_tests.py +0 -0
  346. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_web_hosts.py +0 -0
  347. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_web_routes.py +0 -0
  348. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_python_web_routes_more.py +0 -0
  349. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_react_router.py +0 -0
  350. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_readers_writers_specs.py +0 -0
  351. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_realtime.py +0 -0
  352. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_realtime_native.py +0 -0
  353. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_redact_salt.py +0 -0
  354. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_request_keys.py +0 -0
  355. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_roundtrip.py +0 -0
  356. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_route_specs.py +0 -0
  357. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_route_tables.py +0 -0
  358. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_routes_search_explain.py +0 -0
  359. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_rpc.py +0 -0
  360. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_scip_health.py +0 -0
  361. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_sdk_external.py +0 -0
  362. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_sdk_external_infra.py +0 -0
  363. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_sdk_external_mail.py +0 -0
  364. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_snippet.py +0 -0
  365. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_sockets.py +0 -0
  366. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_spring.py +0 -0
  367. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ssrf.py +0 -0
  368. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_starters_budget.py +0 -0
  369. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_surface.py +0 -0
  370. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_surface_transport.py +0 -0
  371. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift.py +0 -0
  372. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_binding.py +0 -0
  373. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_exact.py +0 -0
  374. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_facts.py +0 -0
  375. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_fields.py +0 -0
  376. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_modules.py +0 -0
  377. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_more.py +0 -0
  378. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_nav_values.py +0 -0
  379. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_parse_errors.py +0 -0
  380. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_props.py +0 -0
  381. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_sdk.py +0 -0
  382. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_testing.py +0 -0
  383. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_swift_values.py +0 -0
  384. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_tests_scope.py +0 -0
  385. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_fields.py +0 -0
  386. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_fields_js_vue.py +0 -0
  387. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_file_specs.py +0 -0
  388. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_frameworks.py +0 -0
  389. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_node_http.py +0 -0
  390. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_ts_src_tsconfig.py +0 -0
  391. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_unguarded.py +0 -0
  392. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_values.py +0 -0
  393. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_viz.py +0 -0
  394. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_vue_nav.py +0 -0
  395. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_watch.py +0 -0
  396. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_webhooks.py +0 -0
  397. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_webhooks_152.py +0 -0
  398. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_webhooks_152b.py +0 -0
  399. {cg_code_graph-0.23.0 → cg_code_graph-0.23.1}/tests/test_websockets.py +0 -0
  400. {cg_code_graph-0.23.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.23.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.23.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)
@@ -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"])]
@@ -137,7 +137,10 @@ def known_origin_text(attrs: dict) -> str | None:
137
137
  return None
138
138
 
139
139
 
140
- _GENERIC_ORIGIN = {"env", "base", "url", "api", "app", "http", "https", "host", "origin", "endpoint", "service", "internal"}
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"}
141
144
 
142
145
 
143
146
  def repos_for_origin(text: str, servers: list[str]) -> list[str] | None:
@@ -146,17 +149,20 @@ def repos_for_origin(text: str, servers: list[str]) -> list[str] | None:
146
149
  ``None`` when the origin is a generic API base (``API_BASE_URL``) and does not name a repo:
147
150
  matching stays as it was. ``[]`` when it names a service that is not one of ``servers``.
148
151
  """
149
- low = text.lower()
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)) + "-"
150
156
  hits = []
151
157
  for name in servers:
152
- token = name.lower()
158
+ token = "-".join(re.findall(r"[a-z0-9]+", re.sub(r"([a-z0-9])([A-Z])", r"\1 \2", name).lower()))
153
159
  if len(token) < 3:
154
160
  continue
155
- if re.search(rf"(^|[^a-z0-9]){re.escape(token)}([^a-z0-9]|$)", low):
161
+ if f"-{token}-" in norm:
156
162
  hits.append(name)
157
163
  if hits:
158
164
  return hits
159
- tokens = [t for t in re.findall(r"[a-z][a-z0-9]+", low) if t not in _GENERIC_ORIGIN]
165
+ tokens = [t for t in re.findall(r"[a-z][a-z0-9]+", split) if t not in _GENERIC_ORIGIN]
160
166
  if not tokens:
161
167
  return None
162
168
  return []
@@ -431,6 +437,7 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
431
437
  by_server[rt["server"]].append(rt)
432
438
  results = []
433
439
  new_edges = []
440
+ matched_origins: set[tuple[str, str]] = set()
434
441
  for client, ep_id, a, _test in http_rows:
435
442
  targets = [s for s in server_names if (s != client or folded_self) and (client not in allow or s in allow[client])]
436
443
  pool = [rt for s in targets for rt in by_server[s]]
@@ -443,7 +450,11 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
443
450
  if origin_text and owners == [] and not res.get("matched") and a.get("origin_kind") != "other":
444
451
  reason = res.get("reason") or ""
445
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
446
455
  res["reason"] = "external (other origin)"
456
+ elif origin_text and res.get("matched"):
457
+ matched_origins.add((client, origin_text))
447
458
  res.update({"endpoint": ep_id, "method": a["method"], "calls": calls_by_ep.get(ep_id, []),
448
459
  "_client": client, "_servers": targets})
449
460
  results.append(res)
@@ -452,6 +463,12 @@ def link_many(repos: list[tuple[str, str, str]], out_db: str, *, allow: dict | N
452
463
  rr = rmap[m["route"]]
453
464
  new_edges.append((ep_id, m["route"], "MATCHES_ROUTE", rr["file"], rr["line"], m["confidence"], CONFIDENCE_RANK[m["confidence"]],
454
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)
455
472
  db.executemany("INSERT INTO edges(src,dst,kind,file,line,confidence,conf_rank,attrs,gate) VALUES (?,?,?,?,?,?,?,?,?)", new_edges)
456
473
  db.commit()
457
474
  subscriptions = pair_subscriber_urls(db, routes, server_names, allow, folded_self)
@@ -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
@@ -62,9 +62,9 @@ STATE = _State({"db": str(ROOT / "out" / "graph.db"), "root": None, "gates": Non
62
62
  "graph_entry": None, "graph_name": None, "graph_arg": False})
63
63
  _MCP_ROOTS: contextvars.ContextVar[list[str] | None] = contextvars.ContextVar("cg_mcp_roots", default=None)
64
64
 
65
- server = MCPServer(
66
- name="code-graph",
67
- instructions=(
65
+ # Reference text (stacks, spec forms, per-feature notes): the MCP resource cg://guide. The initialize
66
+ # `instructions` stay short and directive so agents use cg before grep / file reads.
67
+ GUIDE = (
68
68
  "Code graph of a project: classes, functions, routes, commands, jobs, pages, DB tables/columns, connections, "
69
69
  "config/env keys, each edge with file:line evidence and a confidence (exact / resolved / heuristic). Stacks: "
70
70
  "For a broad question ('how does X work') start with `explore`: source, entry points, call paths and blast radius in one call. "
@@ -119,8 +119,23 @@ server = MCPServer(
119
119
  "issue links) and overlays the graph without changing it. Workflow: write the plan -> `plan_check` (compact "
120
120
  "summary with counts and the top items; details=true for every item with file:line, forbidden paths and open "
121
121
  "findings) -> refine the plan -> `plan_baseline` -> implement -> `index` -> `plan_check(verify=true)` (planned "
122
- "nodes/edges exist, forbidden paths gone or guarded, modified targets changed)."),
123
- )
122
+ "nodes/edges exist, forbidden paths gone or guarded, modified targets changed).")
123
+
124
+ INSTRUCTIONS = (
125
+ "Use cg before grep or opening files for questions about where code is, what calls what, or what a change "
126
+ "affects. `search` finds a symbol; before editing, `impact` (callers up to entry points) or `reaches` (every "
127
+ "dependent) shows what the change affects; `snippet` reads one symbol instead of a whole file; `explore` answers "
128
+ "a broad 'how does X work' in one call. Unsure which graph? Call `graphs`. Fall back to normal search only for "
129
+ "what cg reports as not covered (`coverage`, a `coverage note:` line). Spec forms and stack notes: resource "
130
+ "cg://guide.")
131
+
132
+ server = MCPServer(name="code-graph", instructions=INSTRUCTIONS)
133
+
134
+
135
+ @server.resource("cg://guide", name="guide", description="cg reference: stacks, spec forms, per-feature notes",
136
+ mime_type="text/plain")
137
+ def guide() -> str:
138
+ return GUIDE
124
139
 
125
140
 
126
141
  def _rel_text(txt: str) -> str:
@@ -451,7 +466,8 @@ def _ename(e: dict) -> str:
451
466
  def reaches(targets: list[str], min_confidence: str = "heuristic", group_by: str = "module",
452
467
  include_gated: bool = True, max_per_group: int = 25, paths: bool = True, platform: str | None = None,
453
468
  connection: str | None = None) -> str:
454
- """Reverse transitive dependents of one or more targets (union), e.g.
469
+ """Use before changing a column, table, connection, env key or symbol: everything that depends on it.
470
+ Reverse transitive dependents of one or more targets (union), e.g.
455
471
  ["orders.customer_id", "connection:warehouse", "connection:tenant_*"].
456
472
 
457
473
  Groups: RUNTIME (live; reached from http routes/schedules/jobs/listeners, or main()/exported FFI symbols in
@@ -489,7 +505,7 @@ def reaches(targets: list[str], min_confidence: str = "heuristic", group_by: str
489
505
  route_lines = [Q.route_failure(st, s)["text"] for s in missing if Q.route_failure(st, s)]
490
506
  if route_lines and len(route_lines) == len(missing):
491
507
  return "\n".join(route_lines)
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)"
508
+ return "\n".join(pline + [f"targets: {tl}"]) + f"\nno node matches {', '.join(map(repr, missing))}; try search() with part of the name (spec forms: resource cg://guide)"
493
509
  if not items and connection:
494
510
  return "\n".join(pline + [f"targets: {tl}", f"no dependents recorded for {', '.join(res['targets'])} on connection {connection!r} "
495
511
  f"(connections seen: {Q.seen_text(res.get('connections_seen') or [])})."])
@@ -550,7 +566,7 @@ def reaches(targets: list[str], min_confidence: str = "heuristic", group_by: str
550
566
  @tool
551
567
  def impact(method: str, min_confidence: str = "heuristic", max_items: int = 60, platform: str | None = None,
552
568
  paths: bool = True) -> str:
553
- """Reverse callers of a method (Class::method, short or FQN) up to entry points, with the shortest call path
569
+ """Use before editing a function: what a change to it affects. Reverse callers of a method (Class::method, short or FQN) up to entry points, with the shortest call path
554
570
  from each entry point.
555
571
  platform: only code built for that target (windows, linux, macos, ios, android, web): code under a platform
556
572
  condition that is false there (#[cfg], #if, Platform.OS / Platform.isX, kIsWeb, .ios.ts / .android.ts files,
@@ -666,7 +682,7 @@ CALLER_KINDS = ("CALLS", "INSTANTIATES", "IMPLEMENTED_BY", "OVERRIDDEN_BY", "BOU
666
682
 
667
683
  @tool
668
684
  def callers(symbol: str, min_confidence: str = "heuristic", limit: int = 60) -> str:
669
- """Direct callers of a function / method / class (one level: CALLS, INSTANTIATES, dispatch and framework edges
685
+ """Use to see who calls X right now. Direct callers of a function / method / class (one level: CALLS, INSTANTIATES, dispatch and framework edges
670
686
  into it), each with the call site file:line and confidence. For the full chain up to entry points use impact()."""
671
687
  st = _st()
672
688
  ids = Q.resolve_targets(st, symbol)
@@ -1042,8 +1058,9 @@ def affected(files: list[str] | None = None, base: str | None = None, max_depth:
1042
1058
 
1043
1059
  @tool
1044
1060
  def node(id_or_symbol: str) -> str:
1045
- """Details of one node: kind, FQN, file:line span, module, entry kinds, docblock (PHPDoc), and edge counts
1046
- by kind (in/out) with a few neighbours."""
1061
+ """Use to inspect a symbol without reading its file. Details of one node: kind, FQN, file:line span, module, entry kinds, docblock (PHPDoc), and edge counts
1062
+ by kind (in/out) with a few neighbours. Specs: Class::method | file#name | table.column | table:<t> |
1063
+ route:<METHOD> <uri> | env:<KEY> | page:/path (more: resource cg://guide)."""
1047
1064
  st = _st()
1048
1065
  n = st.node(id_or_symbol)
1049
1066
  if not n:
@@ -1076,7 +1093,7 @@ def node(id_or_symbol: str) -> str:
1076
1093
 
1077
1094
  @tool
1078
1095
  def snippet(id_or_symbol: str, context: int = 0, max_lines: int = 200) -> str:
1079
- """Source of one symbol: a `path:start-end` header then the body with line numbers. Resolves a
1096
+ """Use instead of opening a whole file. Source of one symbol: a `path:start-end` header then the body with line numbers. Resolves a
1080
1097
  node id or a symbol / FQN (as node() and search() do); an ambiguous name lists the candidates
1081
1098
  instead of guessing. context adds lines around the span; max_lines caps the body (truncation noted)."""
1082
1099
  return Q.render_snippet(Q.snippet(_st(), id_or_symbol, context=context, max_lines=max_lines))
@@ -1084,7 +1101,7 @@ def snippet(id_or_symbol: str, context: int = 0, max_lines: int = 200) -> str:
1084
1101
 
1085
1102
  @tool
1086
1103
  def search(name: str, kind: str | None = None, limit: int = 20, platform: str | None = None) -> str:
1087
- """Find nodes by name / FQN substring (case-insensitive), optionally filtered by kind
1104
+ """Use first to find a symbol instead of grep. Finds nodes by name / FQN substring (case-insensitive), optionally filtered by kind
1088
1105
  (class, method, route, command, table, column, connection, config, env, job, admin...). Also matches route
1089
1106
  middleware, guards, auth and access checks (e.g. "auth" finds `auth:api`, `ApiKeyGuard`, `IsAuthenticated`) and
1090
1107
  lists the routes that carry them. Platform-specific symbols carry their targets, e.g. `[ios, android]`.
@@ -1115,7 +1132,7 @@ def explore(query: str, budget_tokens: int = 3000, max_symbols: int = 4) -> str:
1115
1132
  def routes(writes: str | None = None, reaches: list[str] | None = None, missing: str | None = None,
1116
1133
  unguarded: bool = False, strict: bool = False, auth_pattern: str | None = None, max_items: int = 40, paths: bool = True,
1117
1134
  min_confidence: str = "heuristic", platform: str | None = None) -> str:
1118
- """Routes with their middleware / guards / auth, in one call. Optional scope: writes="*" (routes that reach any
1135
+ """Use for route, auth and middleware questions. Routes with their middleware / guards / auth, in one call. Optional scope: writes="*" (routes that reach any
1119
1136
  DB write) or writes="<table>", reaches=[specs] (routes that reach any of these nodes: table, column, connection,
1120
1137
  method, env key...). Optional filters: missing="<name>" keeps routes with no guard whose name contains it (e.g.
1121
1138
  "auth:api", "ApiKeyGuard"), unguarded=true keeps routes with no auth guard (the framework presets' auth guards and
@@ -1154,7 +1171,7 @@ def doctor(root: str | None = None, scip: list[str] | None = None, json_output:
1154
1171
 
1155
1172
  @tool
1156
1173
  def coverage(path: str | None = None, all_files: bool = False, json_output: bool = False) -> str:
1157
- """Which languages and files this index covers. Per language: parser mode (exact, heuristic only when an
1174
+ """Use when cg finds nothing or you need to know if a file is indexed. Which languages and files this index covers. Per language: parser mode (exact, heuristic only when an
1158
1175
  exact-mode indexer such as rust-analyzer or scip-clang is missing, skipped when the toolchain is missing, with the
1159
1176
  install hint) and file completeness (discovered vs indexed, with parse failures, files over the size limit,
1160
1177
  unmapped files outside the source roots, excluded files); unsupported source types by extension or shebang
@@ -1242,7 +1259,7 @@ def stats() -> str:
1242
1259
  @tool
1243
1260
  def downstream(target: str, max_per_kind: int = 25, paths: bool = True, min_confidence: str = "heuristic",
1244
1261
  platform: str | None = None) -> str:
1245
- """Forward dependencies of a node: what it ends up calling/reading. On a combined graph a frontend page goes
1262
+ """Use to see what X ends up calling or reading (page -> routes -> tables). Forward dependencies of a node. On a combined graph a frontend page goes
1246
1263
  page -> composables/components -> HTTP endpoints -> backend routes -> controllers/services -> tables.
1247
1264
  Lists backend routes, tables touched (directly or via columns), columns, connections, config/env keys, each
1248
1265
  with one shortest evidence path. target: page:/reports/:id | app/pages/x.vue | Class::method | ...
@@ -1288,7 +1305,7 @@ def downstream(target: str, max_per_kind: int = 25, paths: bool = True, min_conf
1288
1305
 
1289
1306
  @tool
1290
1307
  def path(source: str, target: str, min_confidence: str = "heuristic", platform: str | None = None) -> str:
1291
- """Shortest forward evidence chain from source to target (e.g. page:/reports/:id ->
1308
+ """Use to answer "how does A reach B". Shortest forward evidence chain from source to target (e.g. page:/reports/:id ->
1292
1309
  SalesReportService::report), one hop per line with file:line and confidence.
1293
1310
  platform: only code built for that target (windows, linux, macos, ios, android, web): code under a platform
1294
1311
  condition that is false there (#[cfg], #if, Platform.OS / Platform.isX, kIsWeb, .ios.ts / .android.ts files,
@@ -1601,7 +1618,7 @@ def _index(root: str | None = None, gates: str | None = None, repo: str | None =
1601
1618
 
1602
1619
  @tool
1603
1620
  def index(root: str | None = None, gates: str | None = None, repo: str | None = None) -> str:
1604
- """Re-index after editing (static analysis only: never boots the app or touches a database).
1621
+ """Use after editing so later answers see the change. Re-index (static analysis only: never boots the app or touches a database).
1605
1622
  On a combined graph (any number of repos): with no arguments every repo is re-indexed from its recorded root and the
1606
1623
  cross-repo link is rebuilt; repo (a name used at link time) re-indexes just that repo; root is matched to the
1607
1624
  recorded repo roots (a repo directory, a path inside one, or a parent of several). A root that matches no repo, or
@@ -1623,7 +1640,7 @@ def index(root: str | None = None, gates: str | None = None, repo: str | None =
1623
1640
 
1624
1641
  @tool
1625
1642
  def graphs() -> str:
1626
- """List the graphs this server can query: name, repo roots, languages, indexed commit and freshness.
1643
+ """Use when unsure which graph a question belongs to. Lists the graphs this server can query: name, repo roots, languages, indexed commit and freshness.
1627
1644
  One `cg-mcp` process serves every registered graph. Pass `graph` to other tools to choose one, or omit it
1628
1645
  and the server resolves from a path in the call, then MCP roots or the working directory, then the configured
1629
1646
  default. An ambiguous choice returns the list instead of guessing."""
@@ -87,6 +87,33 @@ _SCAN_EXTS = ("mts", "cts", "ts", "tsx", "mjs", "cjs", "js", "jsx")
87
87
  _CFG_NAMES = ("nuxt.config.ts", "nuxt.config.mts", "nuxt.config.js", "nuxt.config.mjs", "nuxt.config.cjs")
88
88
  # kept out of the generated tsconfig: build output, native shells, static assets (cg_code_graph/presets/nuxt.yaml)
89
89
  EXCLUDE = sorted(presets.skip_dirs("nuxt"))
90
+ # Nuxt source dirs outside the srcDir: server/ (Nitro: api, routes, middleware, plugins, utils) and the Nuxt 4 shared/
91
+ # dir sit at the root next to app/ (#214)
92
+ SIDE_DIRS = ("server", "shared")
93
+ _SIDE_EXT = re.compile(r"\.(ts|tsx|mts|cts)$")
94
+ _SIDE_SKIP = re.compile(r"\.(test|spec)\.[cm]?[jt]sx?$|\.d\.ts$")
95
+
96
+
97
+ def side_dirs(root: Path, src_dir: str) -> list[str]:
98
+ """Root-level server/ and shared/ of a Nuxt project whose srcDir is not the root (with a root srcDir they are
99
+ already inside it; Nuxt 3's src/server sits inside a src/ srcDir)."""
100
+ if src_dir in ("", "."):
101
+ return []
102
+ return [d for d in SIDE_DIRS if (root / d).is_dir()]
103
+
104
+
105
+ def side_files(root: Path, dirs: list[str]) -> list[str]:
106
+ """TypeScript files under the side dirs (tests and declarations excluded): roots of a prepared run, whose
107
+ .nuxt/tsconfig.app.json leaves server/ to Nitro's own tsconfig."""
108
+ out = []
109
+ for d in dirs:
110
+ for f in sorted((root / d).rglob("*")):
111
+ rel = f.relative_to(root)
112
+ if any(p in COMMON_SKIP or p in EXCLUDE or p.startswith(".") for p in rel.parts[:-1]):
113
+ continue
114
+ if f.is_file() and _SIDE_EXT.search(f.name) and not _SIDE_SKIP.search(f.name):
115
+ out.append(rel.as_posix())
116
+ return out
90
117
 
91
118
 
92
119
  def _exports(f: Path, _seen: set | None = None) -> list[tuple[str, str]]:
@@ -861,10 +888,14 @@ class NuxtPlugin(FrameworkPlugin):
861
888
  f"components{'' if (root / 'node_modules').is_dir() else ', no node_modules so Vue/Nuxt built-ins stay unresolved'}",
862
889
  file=sys.stderr)
863
890
  cfg["kinds"] = kind_rules(self.src_dir)
864
- cfg["src_dirs"] = [self.src_dir]
891
+ # server/ and shared/ are source dirs too (#214); a prepared run lists their files as roots
892
+ self.side_dirs = side_dirs(root, self.src_dir)
893
+ cfg["src_dirs"] = [self.src_dir] + self.side_dirs
894
+ if tsc and self.side_dirs:
895
+ cfg["extra_files"] = list(dict.fromkeys([*(cfg.get("extra_files") or []), *side_files(root, self.side_dirs)]))
865
896
 
866
897
  def contribute(self, project: Project, builder: GraphBuilder, ctx) -> dict:
867
- st = {"prepared": self.prepared, "src_dir": self.src_dir, "pages": 0, "layouts": 0, "ui_global": 0,
898
+ st = {"prepared": self.prepared, "src_dir": self.src_dir, "side_dirs": getattr(self, "side_dirs", []), "pages": 0, "layouts": 0, "ui_global": 0,
868
899
  "i18n_keys_used": 0, "i18n_keys_defined": 0}
869
900
  if self.generated:
870
901
  st["generated_types"] = self.generated
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.23.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
 
@@ -27,6 +27,7 @@ cg_code_graph/guard_facts.py
27
27
  cg_code_graph/hooks.py
28
28
  cg_code_graph/indexer.py
29
29
  cg_code_graph/insecure_transport.py
30
+ cg_code_graph/install_rules.py
30
31
  cg_code_graph/jobs.py
31
32
  cg_code_graph/link.py
32
33
  cg_code_graph/lint_async.py
@@ -271,6 +272,7 @@ tests/test_impact_overrides.py
271
272
  tests/test_index_isolation.py
272
273
  tests/test_inherited_overrides.py
273
274
  tests/test_inline_guards.py
275
+ tests/test_install_rules.py
274
276
  tests/test_issue_192.py
275
277
  tests/test_issue_202.py
276
278
  tests/test_issue_203.py
@@ -305,12 +307,14 @@ tests/test_mass_assignment.py
305
307
  tests/test_mcp.py
306
308
  tests/test_mcp_index.py
307
309
  tests/test_mcp_install.py
310
+ tests/test_mcp_instructions.py
308
311
  tests/test_mcp_multi_graph.py
309
312
  tests/test_native_cfamily.py
310
313
  tests/test_native_concurrency.py
311
314
  tests/test_native_rust.py
312
315
  tests/test_nuxt_import_dirs.py
313
316
  tests/test_nuxt_rootsrc.py
317
+ tests/test_nuxt_side_dirs.py
314
318
  tests/test_packaging.py
315
319
  tests/test_parity.py
316
320
  tests/test_parity_structure.py
@@ -0,0 +1,82 @@
1
+ """`cg install` writes "use cg first" agent rules: a marked section in AGENTS.md and an alwaysApply
2
+ .cursor/rules/cg.mdc. Re-runs replace only the marked section; --no-rules and --global skip them."""
3
+ import pytest
4
+
5
+ from cg_code_graph import install_rules as IR
6
+
7
+
8
+ @pytest.fixture
9
+ def home(monkeypatch, tmp_path):
10
+ root = tmp_path / "home"
11
+ root.mkdir()
12
+ for k in ("HOME", "USERPROFILE"):
13
+ monkeypatch.setenv(k, str(root))
14
+ monkeypatch.setenv("APPDATA", str(root / "AppData" / "Roaming"))
15
+ monkeypatch.setenv("XDG_CONFIG_HOME", str(root / "xdg"))
16
+ monkeypatch.delenv("COPILOT_HOME", raising=False)
17
+ return root
18
+
19
+
20
+ def _main(argv):
21
+ from cg_code_graph.cli import main
22
+ return main(argv)
23
+
24
+
25
+ def test_install_writes_rules_idempotently_and_keeps_user_content(home, tmp_path, capsys):
26
+ proj = tmp_path / "recipe-site"
27
+ proj.mkdir()
28
+ (proj / "AGENTS.md").write_text("# Team notes\n\nRun the linter before pushing.\n")
29
+ assert _main(["install", "--host", "cursor", "--yes", "--dir", str(proj)]) == 0
30
+ out = capsys.readouterr().out
31
+ assert "AGENTS.md (cg agent rules, insert)" in out and "cg.mdc (cg agent rules, insert)" in out
32
+ agents = (proj / "AGENTS.md").read_text()
33
+ mdc = (proj / ".cursor" / "rules" / "cg.mdc").read_text()
34
+ assert agents.startswith("# Team notes\n\nRun the linter before pushing.\n\n" + IR.START)
35
+ assert mdc.startswith("---\n") and "alwaysApply: true" in mdc
36
+ for text in (agents, mdc):
37
+ assert text.count(IR.START) == 1 and text.count(IR.END) == 1
38
+ assert "`search`" in text and "`impact`" in text and "`snippet`" in text and "`graphs`" in text
39
+ # user edits after the section survive; a re-run changes nothing
40
+ (proj / "AGENTS.md").write_text(agents + "\n## Release\n\nTag from main.\n")
41
+ agents2 = (proj / "AGENTS.md").read_text()
42
+ assert _main(["install", "--host", "cursor", "--yes", "--dir", str(proj)]) == 0
43
+ assert (proj / "AGENTS.md").read_text() == agents2
44
+ assert (proj / ".cursor" / "rules" / "cg.mdc").read_text() == mdc
45
+ # an outdated section is replaced in place
46
+ stale = agents2.replace("- `snippet`", "- `old line`")
47
+ (proj / "AGENTS.md").write_text(stale)
48
+ assert _main(["install", "--host", "cursor", "--yes", "--dir", str(proj)]) == 0
49
+ assert (proj / "AGENTS.md").read_text() == agents2
50
+ # uninstall removes only the section, and the rule file it created
51
+ assert _main(["uninstall", "--host", "cursor", "--yes", "--dir", str(proj)]) == 0
52
+ left = (proj / "AGENTS.md").read_text()
53
+ assert IR.START not in left and "Run the linter before pushing." in left and "Tag from main." in left
54
+ assert not (proj / ".cursor").exists()
55
+
56
+
57
+ def test_existing_cursor_rule_gains_header_once(tmp_path):
58
+ proj = tmp_path / "p"
59
+ (proj / ".cursor" / "rules").mkdir(parents=True)
60
+ (proj / ".cursor" / "rules" / "cg.mdc").write_text("Prefer small diffs.\n")
61
+ plans = {p["path"].rsplit("/", 1)[-1]: p for p in IR.plans(proj)}
62
+ new = plans["cg.mdc"]["new"]
63
+ assert new.startswith(IR.MDC_HEADER) and "Prefer small diffs.\n" in new and new.count(IR.START) == 1
64
+ (proj / ".cursor" / "rules" / "cg.mdc").write_text(new)
65
+ assert {p["action"] for p in IR.plans(proj)} == {"insert", "noop"} # AGENTS.md still new, cg.mdc current
66
+
67
+
68
+ def test_no_rules_and_global_skip(home, tmp_path, capsys):
69
+ proj = tmp_path / "p"
70
+ proj.mkdir()
71
+ assert _main(["install", "--host", "cursor", "--yes", "--no-rules", "--dir", str(proj)]) == 0
72
+ assert (proj / ".cursor" / "mcp.json").is_file()
73
+ assert not (proj / "AGENTS.md").exists() and not (proj / ".cursor" / "rules").exists()
74
+ db = tmp_path / "g.db"
75
+ db.write_bytes(b"")
76
+ assert _main(["install", "--global", "--host", "cursor", "--yes", "--db", str(db), "--dir", str(proj)]) == 0
77
+ assert not (proj / "AGENTS.md").exists() and not (proj / ".cursor" / "rules").exists()
78
+ assert not list(home.rglob("AGENTS.md")) and not list(home.rglob("cg.mdc"))
79
+ # dry run previews the rules and writes nothing
80
+ assert _main(["install", "--host", "cursor", "--dry-run", "--dir", str(proj)]) == 0
81
+ out = capsys.readouterr().out
82
+ assert IR.START in out and not (proj / "AGENTS.md").exists()