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