pycode-kg 0.19.2__tar.gz → 0.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/PKG-INFO +15 -17
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/README.md +7 -7
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/pyproject.toml +42 -48
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/__init__.py +3 -3
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/analysis/framework_detector.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/app.py +28 -28
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/architecture.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/__init__.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_analyze.py +4 -4
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_architecture.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_build.py +17 -21
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_build_full.py +14 -24
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_explain.py +4 -12
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_init.py +4 -7
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_mcp.py +8 -8
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_model.py +2 -2
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_query.py +9 -27
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_snapshot.py +0 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_viz.py +2 -2
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/options.py +6 -6
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/graph.py +5 -3
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/kg.py +15 -17
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/mcp_server.py +43 -36
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/module/__init__.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/module/extractor.py +2 -2
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg_thorough_analysis.py +20 -20
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/snapshots.py +1 -1
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/viz3d.py +40 -42
- pycode_kg-0.19.2/src/pycode_kg/build_pycodekg_lancedb.py +0 -15
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/LICENSE +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/.DS_Store +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/__main__.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/analysis/__init__.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/analysis/bridge.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/analysis/centrality.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/analysis/hybrid_rank.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/build_pycodekg_sqlite.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_bridges.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_centrality.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_framework_nodes.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/cmd_hooks.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/cli/main.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/config.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/explain.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/index.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/layout3d.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/module/base.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/module/types.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg_query.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg_snippet_packer.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg_viz.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/pycodekg_viz3d.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/ranking/__init__.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/ranking/cli_rank.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/ranking/coderank.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/sql/004_add_centrality_table.sql +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/store.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/utils.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/visitor.py +0 -0
- {pycode_kg-0.19.2 → pycode_kg-0.20.0}/src/pycode_kg/viz3d_timeline.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycode-kg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: A tool to build a searchable knowledge graph from Python repositories
|
|
5
5
|
License-Expression: Elastic-2.0
|
|
6
6
|
License-File: LICENSE
|
|
7
|
-
Keywords: knowledge-graph,code-analysis,ast,
|
|
7
|
+
Keywords: knowledge-graph,code-analysis,ast,sqlite-vec,sqlite,semantic-search
|
|
8
8
|
Author: Eric G. Suchanek, PhD
|
|
9
|
-
Author-email: suchanek@
|
|
9
|
+
Author-email: suchanek@flux-frontiers.com
|
|
10
10
|
Requires-Python: >=3.12,<3.14
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -25,14 +25,12 @@ Requires-Dist: PyQt5 (>=5.15.0) ; extra == "viz3d"
|
|
|
25
25
|
Requires-Dist: click (>=8.1.0,<9)
|
|
26
26
|
Requires-Dist: detect-secrets (>=1.5.0) ; extra == "all"
|
|
27
27
|
Requires-Dist: detect-secrets (>=1.5.0) ; extra == "dev"
|
|
28
|
-
Requires-Dist: doc-kg (>=0.
|
|
29
|
-
Requires-Dist: doc-kg (>=0.
|
|
30
|
-
Requires-Dist: kgmodule-utils[semantic] (>=0.
|
|
28
|
+
Requires-Dist: doc-kg (>=0.18.1) ; extra == "dev"
|
|
29
|
+
Requires-Dist: doc-kg (>=0.18.1) ; extra == "kgdeps"
|
|
30
|
+
Requires-Dist: kgmodule-utils[semantic,sqlite-vec] (>=0.6.2)
|
|
31
31
|
Requires-Dist: markdown (>=3.6) ; extra == "all"
|
|
32
32
|
Requires-Dist: markdown (>=3.6) ; extra == "viz3d"
|
|
33
33
|
Requires-Dist: mcp (>=1.0.0)
|
|
34
|
-
Requires-Dist: mypy (>=1.10.0) ; extra == "all"
|
|
35
|
-
Requires-Dist: mypy (>=1.10.0) ; extra == "dev"
|
|
36
34
|
Requires-Dist: numpy (>=1.24.0)
|
|
37
35
|
Requires-Dist: pandas (>=2.0.0)
|
|
38
36
|
Requires-Dist: param (>=2.0.0) ; extra == "all"
|
|
@@ -43,8 +41,6 @@ Requires-Dist: plotly (>=5.14.0) ; extra == "all"
|
|
|
43
41
|
Requires-Dist: plotly (>=5.14.0) ; extra == "viz"
|
|
44
42
|
Requires-Dist: pre-commit (>=4.5.1) ; extra == "all"
|
|
45
43
|
Requires-Dist: pre-commit (>=4.5.1) ; extra == "dev"
|
|
46
|
-
Requires-Dist: pylint (>=4.0.5) ; extra == "all"
|
|
47
|
-
Requires-Dist: pylint (>=4.0.5) ; extra == "dev"
|
|
48
44
|
Requires-Dist: pytest (>=8.0.0) ; extra == "all"
|
|
49
45
|
Requires-Dist: pytest (>=8.0.0) ; extra == "dev"
|
|
50
46
|
Requires-Dist: pytest-cov (>=5.0.0) ; extra == "all"
|
|
@@ -66,6 +62,8 @@ Requires-Dist: torch (>=2.5.1)
|
|
|
66
62
|
Requires-Dist: trame-vtk (>=2.0.0) ; extra == "all"
|
|
67
63
|
Requires-Dist: trame-vtk (>=2.0.0) ; extra == "viz3d"
|
|
68
64
|
Requires-Dist: transformers (>=4.40.0,<4.57)
|
|
65
|
+
Requires-Dist: ty (>=0.0.41) ; extra == "all"
|
|
66
|
+
Requires-Dist: ty (>=0.0.41) ; extra == "dev"
|
|
69
67
|
Project-URL: Homepage, https://github.com/Flux-Frontiers/pycode_kg
|
|
70
68
|
Project-URL: Repository, https://github.com/Flux-Frontiers/pycode_kg
|
|
71
69
|
Description-Content-Type: text/markdown
|
|
@@ -77,7 +75,7 @@ Description-Content-Type: text/markdown
|
|
|
77
75
|
|
|
78
76
|
[](https://www.python.org/)
|
|
79
77
|
[](https://www.elastic.co/licensing/elastic-license)
|
|
80
|
-
[](https://github.com/Flux-Frontiers/pycode_kg/releases)
|
|
81
79
|
[](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
|
|
82
80
|
[](https://python-poetry.org/)
|
|
83
81
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
@@ -86,7 +84,7 @@ Description-Content-Type: text/markdown
|
|
|
86
84
|
|
|
87
85
|
**PyCodeKG turns a Python codebase into a deterministic, queryable knowledge graph — and uses it to produce architectural analyses you can act on, with or without an LLM in the loop.**
|
|
88
86
|
|
|
89
|
-
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A
|
|
87
|
+
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A sqlite-vec vector index sits alongside the graph so that *"authentication flow"* and *"verify_jwt"* both find the right place to start exploring. From there you can rank functions by structural importance, trace fan-in across import aliases, detect circular imports and dead code, render the call graph in 3D, snapshot metrics for diffing across releases, or hand the whole thing to Claude over MCP.
|
|
90
88
|
|
|
91
89
|
The original motivation was simple: **produce thorough, defensible analyses of Python codebases that don't depend on inference**. Every result is computed from the AST and the graph — no model is asked to guess. When an LLM is present, it consumes the *same* grounded output as a structured context pack, and the hallucinations that plague "embed-the-repo" tools largely disappear.
|
|
92
90
|
|
|
@@ -197,7 +195,7 @@ That's the recommended path. Variants (minimal install, MCP-only, contributor se
|
|
|
197
195
|
|
|
198
196
|
Search is hybrid by design. A query like *"authentication flow"* runs in two phases:
|
|
199
197
|
|
|
200
|
-
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and
|
|
198
|
+
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and sqlite-vec returns the `k` closest functions, classes, and modules by exact cosine similarity.
|
|
201
199
|
2. **Graph expansion phase** — each seed hit is expanded `hop` BFS steps along the typed edges (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`) so call chains and module relationships surface alongside the names that matched.
|
|
202
200
|
|
|
203
201
|
**Structure is treated as ground truth; the embeddings are strictly an acceleration layer.** When the graph and the vector index disagree, the graph wins. This is why fan-in lookups are accurate even for same-named symbols across modules — `RESOLVES_TO` edges bridge call sites through their import aliases, and `callers()` does a two-phase reverse traversal that grep simply cannot replicate.
|
|
@@ -231,7 +229,7 @@ src/pycode_kg/
|
|
|
231
229
|
├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
|
|
232
230
|
├── graph.py # GraphBuilder: file discovery + dispatch
|
|
233
231
|
├── store.py # SQLite persistence + canonical edges
|
|
234
|
-
├── index.py #
|
|
232
|
+
├── index.py # sqlite-vec semantic index
|
|
235
233
|
├── pycodekg.py # Public façade
|
|
236
234
|
├── pycodekg_query.py # Hybrid query
|
|
237
235
|
├── pycodekg_snippet_packer.py # Source-grounded packs
|
|
@@ -273,13 +271,13 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
273
271
|
|
|
274
272
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
275
273
|
|
|
276
|
-
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.
|
|
274
|
+
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.20.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
|
|
277
275
|
|
|
278
276
|
```bibtex
|
|
279
277
|
@software{suchanek_pycode_kg,
|
|
280
278
|
author = {Suchanek, Eric G.},
|
|
281
279
|
title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
|
|
282
|
-
version = {0.
|
|
280
|
+
version = {0.20.0},
|
|
283
281
|
year = {2026},
|
|
284
282
|
publisher = {Flux-Frontiers},
|
|
285
283
|
url = {https://github.com/Flux-Frontiers/pycode_kg},
|
|
@@ -299,7 +297,7 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
299
297
|
|
|
300
298
|
- **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
|
|
301
299
|
- Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
|
|
302
|
-
-
|
|
300
|
+
- sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
|
|
303
301
|
|
|
304
302
|
---
|
|
305
303
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
[](https://www.python.org/)
|
|
7
7
|
[](https://www.elastic.co/licensing/elastic-license)
|
|
8
|
-
[](https://github.com/Flux-Frontiers/pycode_kg/releases)
|
|
9
9
|
[](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
|
|
10
10
|
[](https://python-poetry.org/)
|
|
11
11
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
**PyCodeKG turns a Python codebase into a deterministic, queryable knowledge graph — and uses it to produce architectural analyses you can act on, with or without an LLM in the loop.**
|
|
16
16
|
|
|
17
|
-
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A
|
|
17
|
+
It walks the AST of every module, class, function, and method in your repo, extracts the typed relationships that actually hold the code together (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`), and stores the result in SQLite. A sqlite-vec vector index sits alongside the graph so that *"authentication flow"* and *"verify_jwt"* both find the right place to start exploring. From there you can rank functions by structural importance, trace fan-in across import aliases, detect circular imports and dead code, render the call graph in 3D, snapshot metrics for diffing across releases, or hand the whole thing to Claude over MCP.
|
|
18
18
|
|
|
19
19
|
The original motivation was simple: **produce thorough, defensible analyses of Python codebases that don't depend on inference**. Every result is computed from the AST and the graph — no model is asked to guess. When an LLM is present, it consumes the *same* grounded output as a structured context pack, and the hallucinations that plague "embed-the-repo" tools largely disappear.
|
|
20
20
|
|
|
@@ -125,7 +125,7 @@ That's the recommended path. Variants (minimal install, MCP-only, contributor se
|
|
|
125
125
|
|
|
126
126
|
Search is hybrid by design. A query like *"authentication flow"* runs in two phases:
|
|
127
127
|
|
|
128
|
-
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and
|
|
128
|
+
1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and sqlite-vec returns the `k` closest functions, classes, and modules by exact cosine similarity.
|
|
129
129
|
2. **Graph expansion phase** — each seed hit is expanded `hop` BFS steps along the typed edges (`CONTAINS`, `CALLS`, `IMPORTS`, `INHERITS`, `RESOLVES_TO`) so call chains and module relationships surface alongside the names that matched.
|
|
130
130
|
|
|
131
131
|
**Structure is treated as ground truth; the embeddings are strictly an acceleration layer.** When the graph and the vector index disagree, the graph wins. This is why fan-in lookups are accurate even for same-named symbols across modules — `RESOLVES_TO` edges bridge call sites through their import aliases, and `callers()` does a two-phase reverse traversal that grep simply cannot replicate.
|
|
@@ -159,7 +159,7 @@ src/pycode_kg/
|
|
|
159
159
|
├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
|
|
160
160
|
├── graph.py # GraphBuilder: file discovery + dispatch
|
|
161
161
|
├── store.py # SQLite persistence + canonical edges
|
|
162
|
-
├── index.py #
|
|
162
|
+
├── index.py # sqlite-vec semantic index
|
|
163
163
|
├── pycodekg.py # Public façade
|
|
164
164
|
├── pycodekg_query.py # Hybrid query
|
|
165
165
|
├── pycodekg_snippet_packer.py # Source-grounded packs
|
|
@@ -201,13 +201,13 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
201
201
|
|
|
202
202
|
[](https://zenodo.org/badge/latestdoi/1202379010)
|
|
203
203
|
|
|
204
|
-
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.
|
|
204
|
+
> Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.20.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
|
|
205
205
|
|
|
206
206
|
```bibtex
|
|
207
207
|
@software{suchanek_pycode_kg,
|
|
208
208
|
author = {Suchanek, Eric G.},
|
|
209
209
|
title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
|
|
210
|
-
version = {0.
|
|
210
|
+
version = {0.20.0},
|
|
211
211
|
year = {2026},
|
|
212
212
|
publisher = {Flux-Frontiers},
|
|
213
213
|
url = {https://github.com/Flux-Frontiers/pycode_kg},
|
|
@@ -227,7 +227,7 @@ If you use PyCodeKG in your research or project, please cite it:
|
|
|
227
227
|
|
|
228
228
|
- **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
|
|
229
229
|
- Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
|
|
230
|
-
-
|
|
230
|
+
- sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# pyproject.toml — PyCodeKG package configuration (PEP 621)
|
|
2
2
|
#
|
|
3
3
|
# Author: Eric G. Suchanek, PhD
|
|
4
|
-
# Last Revision: 2026-
|
|
4
|
+
# Last Revision: 2026-07-15
|
|
5
5
|
#
|
|
6
6
|
# Build system : Poetry 2.x with PEP 621 [project] table
|
|
7
7
|
#
|
|
8
8
|
# Quick install (pip)
|
|
9
9
|
# -------------------
|
|
10
|
-
# pip install -e ".[dev]" core + dev tools (pytest, ruff,
|
|
10
|
+
# pip install -e ".[dev]" core + dev tools (pytest, ruff, ty, etc.)
|
|
11
11
|
# pip install -e ".[viz]" core + Streamlit/Plotly/PyVis visualizer
|
|
12
12
|
# pip install -e ".[viz3d]" core + PyVista 3D visualizer
|
|
13
13
|
# pip install -e ".[kgdeps]" core + KG integrations (doc-kg, agent-kg)
|
|
@@ -46,29 +46,19 @@ build-backend = "poetry.core.masonry.api"
|
|
|
46
46
|
[tool.poetry]
|
|
47
47
|
packages = [{ include = "pycode_kg", from = "src" }]
|
|
48
48
|
|
|
49
|
-
[tool.poetry.group.dev.dependencies]
|
|
50
|
-
detect-secrets = ">=1.5.0"
|
|
51
|
-
mypy = ">=1.10.0"
|
|
52
|
-
pdoc = ">=14.0.0"
|
|
53
|
-
pre-commit = ">=4.5.1"
|
|
54
|
-
pylint = ">=4.0.5"
|
|
55
|
-
pytest = ">=8.0.0"
|
|
56
|
-
pytest-cov = ">=5.0.0"
|
|
57
|
-
ruff = ">=0.4.0"
|
|
58
|
-
|
|
59
49
|
# ---------------------------------------------------------------------------
|
|
60
50
|
# PEP 621 project metadata
|
|
61
51
|
# ---------------------------------------------------------------------------
|
|
62
52
|
[project]
|
|
63
53
|
name = "pycode-kg"
|
|
64
|
-
version = "0.
|
|
54
|
+
version = "0.20.0"
|
|
65
55
|
description = "A tool to build a searchable knowledge graph from Python repositories"
|
|
66
56
|
readme = "README.md"
|
|
67
57
|
license = "Elastic-2.0"
|
|
68
58
|
authors = [
|
|
69
|
-
{ name = "Eric G. Suchanek, PhD", email = "suchanek@
|
|
59
|
+
{ name = "Eric G. Suchanek, PhD", email = "suchanek@flux-frontiers.com" }
|
|
70
60
|
]
|
|
71
|
-
keywords = ["knowledge-graph", "code-analysis", "ast", "
|
|
61
|
+
keywords = ["knowledge-graph", "code-analysis", "ast", "sqlite-vec", "sqlite", "semantic-search"]
|
|
72
62
|
classifiers = [
|
|
73
63
|
"Development Status :: 4 - Beta",
|
|
74
64
|
"Intended Audience :: Developers",
|
|
@@ -89,20 +79,19 @@ dependencies = [
|
|
|
89
79
|
"sentence-transformers>=5.4.1",
|
|
90
80
|
"torch>=2.5.1",
|
|
91
81
|
"transformers>=4.40.0,<4.57",
|
|
92
|
-
"kgmodule-utils[semantic]>=0.
|
|
82
|
+
"kgmodule-utils[semantic,sqlite-vec]>=0.6.2",
|
|
93
83
|
]
|
|
94
84
|
|
|
95
85
|
[project.optional-dependencies]
|
|
96
86
|
dev = [
|
|
97
87
|
"detect-secrets>=1.5.0",
|
|
98
|
-
"
|
|
88
|
+
"ty>=0.0.41",
|
|
99
89
|
"pdoc>=14.0.0",
|
|
100
90
|
"pre-commit>=4.5.1",
|
|
101
|
-
"pylint>=4.0.5",
|
|
102
91
|
"pytest>=8.0.0",
|
|
103
92
|
"pytest-cov>=5.0.0",
|
|
104
93
|
"ruff>=0.4.0",
|
|
105
|
-
"doc-kg>=0.
|
|
94
|
+
"doc-kg>=0.18.1",
|
|
106
95
|
# agent-kg not yet on PyPI — install manually: pip install git+https://github.com/Flux-Frontiers/agent_kg.git
|
|
107
96
|
]
|
|
108
97
|
viz = [
|
|
@@ -121,17 +110,15 @@ viz3d = [
|
|
|
121
110
|
|
|
122
111
|
# note that dockg is on pypi; agent-kg is not yet — install manually from git
|
|
123
112
|
kgdeps = [
|
|
124
|
-
"doc-kg>=0.
|
|
113
|
+
"doc-kg>=0.18.1",
|
|
125
114
|
]
|
|
126
115
|
all = [
|
|
127
116
|
"detect-secrets>=1.5.0",
|
|
128
117
|
"markdown>=3.6",
|
|
129
|
-
"mypy>=1.10.0",
|
|
130
118
|
"param>=2.0.0",
|
|
131
119
|
"pdoc>=14.0.0",
|
|
132
120
|
"plotly>=5.14.0",
|
|
133
121
|
"pre-commit>=4.5.1",
|
|
134
|
-
"pylint>=4.0.5",
|
|
135
122
|
"PyQt5>=5.15.0",
|
|
136
123
|
"pytest>=8.0.0",
|
|
137
124
|
"pytest-cov>=5.0.0",
|
|
@@ -141,6 +128,7 @@ all = [
|
|
|
141
128
|
"ruff>=0.4.0",
|
|
142
129
|
"streamlit>=1.35.0",
|
|
143
130
|
"trame-vtk>=2.0.0",
|
|
131
|
+
"ty>=0.0.41",
|
|
144
132
|
]
|
|
145
133
|
|
|
146
134
|
[project.urls]
|
|
@@ -152,7 +140,7 @@ pycodekg = "pycode_kg.cli.main:cli"
|
|
|
152
140
|
pycodekg-analyze = "pycode_kg.cli.cmd_analyze:analyze"
|
|
153
141
|
pycodekg-architecture = "pycode_kg.cli.cmd_architecture:architecture"
|
|
154
142
|
pycodekg-build = "pycode_kg.cli.cmd_build_full:build"
|
|
155
|
-
pycodekg-build-
|
|
143
|
+
pycodekg-build-index = "pycode_kg.cli.cmd_build:build_index"
|
|
156
144
|
pycodekg-build-sqlite = "pycode_kg.cli.cmd_build:build_sqlite"
|
|
157
145
|
pycodekg-centrality = "pycode_kg.cli.cmd_centrality:cmd_centrality"
|
|
158
146
|
pycodekg-download-model = "pycode_kg.cli.cmd_model:download_model"
|
|
@@ -172,41 +160,47 @@ pycodekg-viz3d = "pycode_kg.cli.cmd_viz:viz3d"
|
|
|
172
160
|
[tool.ruff]
|
|
173
161
|
line-length = 100
|
|
174
162
|
target-version = "py312"
|
|
163
|
+
# Vendored Claude Code skills — not project code. The pre-commit hook's
|
|
164
|
+
# exclude can't cover these (it runs with pass_filenames: false), so the
|
|
165
|
+
# exclusion must live here.
|
|
166
|
+
extend-exclude = [".claude"]
|
|
175
167
|
|
|
176
168
|
[tool.ruff.lint]
|
|
177
|
-
|
|
169
|
+
# B023, BLE001, PLC0415 replace the retired pylint hook's cell-var-from-loop,
|
|
170
|
+
# broad-exception-caught, and import-outside-toplevel checks.
|
|
171
|
+
select = ["E", "F", "W", "I", "UP", "B023", "BLE001", "PLC0415"]
|
|
178
172
|
ignore = ["E501"]
|
|
179
173
|
|
|
180
|
-
[tool.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
174
|
+
[tool.ruff.lint.per-file-ignores]
|
|
175
|
+
# viz3d is GUI code full of deliberate lazy imports (optional Qt/pyvista deps).
|
|
176
|
+
"src/pycode_kg/viz3d.py" = ["PLC0415"]
|
|
177
|
+
# Test imports are often deliberately lazy — they must run after sys.modules
|
|
178
|
+
# mocks are installed.
|
|
179
|
+
"tests/**" = ["PLC0415"]
|
|
180
|
+
|
|
181
|
+
[tool.ty.environment]
|
|
182
|
+
python-version = "3.12"
|
|
183
|
+
root = ["src"]
|
|
184
|
+
|
|
185
|
+
[tool.ty.rules]
|
|
186
|
+
# Be lenient about third-party stubs (mirrors mypy's ignore_missing_imports).
|
|
187
|
+
unresolved-import = "ignore"
|
|
188
|
+
# viz3d.py carries `# ty: ignore` suppressions for param/PyQt5/pyvista false
|
|
189
|
+
# positives. Those libraries live in the optional viz/viz3d extras, so in the
|
|
190
|
+
# lean CI install the imports are Unknown, the errors don't fire, and the
|
|
191
|
+
# ignores look "unused". Don't fail the build on that — the suppressions are
|
|
192
|
+
# still honored locally where the extras (and the errors) are present.
|
|
193
|
+
unused-ignore-comment = "ignore"
|
|
186
194
|
|
|
187
195
|
[tool.pytest.ini_options]
|
|
188
|
-
testpaths
|
|
189
|
-
addopts
|
|
196
|
+
testpaths = ["tests"]
|
|
197
|
+
addopts = "-v --tb=short"
|
|
198
|
+
pythonpath = ["src"]
|
|
190
199
|
markers = [
|
|
191
200
|
"slow: marks tests as slow (deselect with '-m not slow')",
|
|
192
|
-
"integration: marks tests that exercise real external dependencies (model,
|
|
193
|
-
]
|
|
194
|
-
|
|
195
|
-
[tool.pylint.messages_control]
|
|
196
|
-
disable = ["all"]
|
|
197
|
-
enable = [
|
|
198
|
-
"broad-exception-caught", # W0718
|
|
199
|
-
"cell-var-from-loop", # W0640
|
|
200
|
-
"cyclic-import", # R0401
|
|
201
|
-
"import-outside-toplevel", # C0415
|
|
202
|
-
"undefined-variable", # E0602
|
|
201
|
+
"integration: marks tests that exercise real external dependencies (model, sqlite-vec)",
|
|
203
202
|
]
|
|
204
203
|
|
|
205
|
-
[tool.pylint.imports]
|
|
206
|
-
# The kg → pycodekg_thorough_analysis cycle is broken at runtime by a lazy
|
|
207
|
-
# import inside PyCodeKG.analyze(). Pylint's static analysis can't see that.
|
|
208
|
-
ignored-modules = ["pycode_kg.pycodekg_thorough_analysis"]
|
|
209
|
-
|
|
210
204
|
# ---------------------------------------------------------------------------
|
|
211
205
|
# PyCodeKG / DocKG index configuration
|
|
212
206
|
# ---------------------------------------------------------------------------
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
pycode_kg: A tool to build a searchable knowledge graph from Python repositories.
|
|
3
3
|
|
|
4
|
-
Pure AST extraction → SQLite (authoritative) →
|
|
4
|
+
Pure AST extraction → SQLite (authoritative) → sqlite-vec (semantic index).
|
|
5
5
|
|
|
6
6
|
Public API
|
|
7
7
|
----------
|
|
@@ -9,7 +9,7 @@ Primary entry point::
|
|
|
9
9
|
|
|
10
10
|
from pycode_kg import PyCodeKG
|
|
11
11
|
|
|
12
|
-
kg = PyCodeKG(repo_root, db_path
|
|
12
|
+
kg = PyCodeKG(repo_root, db_path)
|
|
13
13
|
stats = kg.build(wipe=True)
|
|
14
14
|
result = kg.query("database connection setup")
|
|
15
15
|
pack = kg.pack("configuration loading")
|
|
@@ -32,7 +32,7 @@ KGModule SDK (build new domain KGs)::
|
|
|
32
32
|
from pycode_kg import KGModule, KGExtractor, PyCodeKGExtractor, NodeSpec, EdgeSpec
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
|
-
__version__ = "0.
|
|
35
|
+
__version__ = "0.20.0"
|
|
36
36
|
__author__ = "Eric G. Suchanek, PhD"
|
|
37
37
|
|
|
38
38
|
# Low-level primitives (locked v0 contract)
|
|
@@ -62,7 +62,7 @@ def detect_framework_nodes(
|
|
|
62
62
|
# against the module_connectivity metric. Both signals end up keyed by
|
|
63
63
|
# bare module path (e.g. "src/pycode_kg/store.py"), which we map to "mod:..."
|
|
64
64
|
# IDs for output.
|
|
65
|
-
from pycode_kg.analysis.centrality import ( #
|
|
65
|
+
from pycode_kg.analysis.centrality import ( # noqa: PLC0415
|
|
66
66
|
StructuralImportanceRanker,
|
|
67
67
|
aggregate_module_scores,
|
|
68
68
|
)
|
|
@@ -57,7 +57,7 @@ _REL_COLOR: dict[str, str] = {
|
|
|
57
57
|
import os as _os # noqa: E402
|
|
58
58
|
|
|
59
59
|
_DEFAULT_DB = _os.environ.get("PYCODEKG_DB", ".pycodekg/graph.sqlite")
|
|
60
|
-
|
|
60
|
+
_DEFAULT_VECTORS = _os.environ.get("PYCODEKG_VECTORS", ".pycodekg/vectors.sqlite")
|
|
61
61
|
|
|
62
62
|
# ---------------------------------------------------------------------------
|
|
63
63
|
# Page config (must be first Streamlit call)
|
|
@@ -147,7 +147,7 @@ def _get_store() -> GraphStore | None:
|
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
@st.cache_resource(show_spinner="Loading PyCodeKG (embedder may take a moment)…")
|
|
150
|
-
def _load_kg(repo_root: str, db_path: str,
|
|
150
|
+
def _load_kg(repo_root: str, db_path: str, vectors_path: str, model: str):
|
|
151
151
|
"""
|
|
152
152
|
Load and cache a ``PyCodeKG`` instance for the given configuration.
|
|
153
153
|
|
|
@@ -157,16 +157,16 @@ def _load_kg(repo_root: str, db_path: str, lancedb_dir: str, model: str):
|
|
|
157
157
|
|
|
158
158
|
:param repo_root: Root directory of the Python repository to analyse.
|
|
159
159
|
:param db_path: Path to the SQLite graph database.
|
|
160
|
-
:param
|
|
160
|
+
:param vectors_path: Path to the sqlite-vec vector store.
|
|
161
161
|
:param model: Name of the sentence-transformer embedding model to use.
|
|
162
162
|
:return: An initialised ``PyCodeKG`` instance.
|
|
163
163
|
"""
|
|
164
|
-
from pycode_kg import PyCodeKG #
|
|
164
|
+
from pycode_kg import PyCodeKG # noqa: PLC0415
|
|
165
165
|
|
|
166
166
|
return PyCodeKG(
|
|
167
167
|
repo_root=repo_root,
|
|
168
168
|
db_path=db_path,
|
|
169
|
-
|
|
169
|
+
vectors_path=vectors_path,
|
|
170
170
|
model=model,
|
|
171
171
|
)
|
|
172
172
|
|
|
@@ -592,7 +592,7 @@ def _render_node_detail(node: dict, store: GraphStore | None = None) -> None:
|
|
|
592
592
|
(node_id, node_id),
|
|
593
593
|
).fetchall()
|
|
594
594
|
if rows:
|
|
595
|
-
import pandas as pd #
|
|
595
|
+
import pandas as pd # noqa: PLC0415
|
|
596
596
|
|
|
597
597
|
edf = pd.DataFrame([{"src": r[0], "rel": r[1], "dst": r[2]} for r in rows])
|
|
598
598
|
st.dataframe(edf, use_container_width=True, hide_index=True)
|
|
@@ -694,12 +694,12 @@ def _render_sidebar() -> dict:
|
|
|
694
694
|
"""
|
|
695
695
|
Render the sidebar controls and return a configuration dictionary.
|
|
696
696
|
|
|
697
|
-
Exposes controls for the SQLite path, repo root,
|
|
697
|
+
Exposes controls for the SQLite path, repo root, sqlite-vec store path,
|
|
698
698
|
embedding model, query parameters (k, hops, relations, include_symbols),
|
|
699
699
|
graph display options (max nodes, physics, height), and build buttons
|
|
700
700
|
for the graph and semantic index.
|
|
701
701
|
|
|
702
|
-
:return: A dict with keys ``db_path``, ``repo_root``, ``
|
|
702
|
+
:return: A dict with keys ``db_path``, ``repo_root``, ``vectors_path``,
|
|
703
703
|
``model``, ``k``, ``hop``, ``rels``, ``include_symbols``,
|
|
704
704
|
``max_graph_nodes``, ``physics_on``, ``graph_height``, and ``store``.
|
|
705
705
|
"""
|
|
@@ -738,10 +738,10 @@ def _render_sidebar() -> dict:
|
|
|
738
738
|
value=str(Path.cwd()),
|
|
739
739
|
help="Root directory of the Python repository to analyse",
|
|
740
740
|
)
|
|
741
|
-
|
|
742
|
-
"
|
|
743
|
-
value=
|
|
744
|
-
help="
|
|
741
|
+
vectors_path = st.sidebar.text_input(
|
|
742
|
+
"Vector store path",
|
|
743
|
+
value=_DEFAULT_VECTORS,
|
|
744
|
+
help="Path to the sqlite-vec vector store",
|
|
745
745
|
)
|
|
746
746
|
model = st.sidebar.selectbox(
|
|
747
747
|
"Embedding model",
|
|
@@ -789,12 +789,12 @@ def _render_sidebar() -> dict:
|
|
|
789
789
|
)
|
|
790
790
|
build_index_btn = build_col2.button(
|
|
791
791
|
"🧠 Build Index",
|
|
792
|
-
help="Embed nodes →
|
|
792
|
+
help="Embed nodes → sqlite-vec (requires graph to exist)",
|
|
793
793
|
use_container_width=True,
|
|
794
794
|
)
|
|
795
795
|
build_all_btn = st.sidebar.button(
|
|
796
796
|
"⚡ Build All (graph + index)",
|
|
797
|
-
help="Full pipeline: AST → SQLite →
|
|
797
|
+
help="Full pipeline: AST → SQLite → sqlite-vec",
|
|
798
798
|
use_container_width=True,
|
|
799
799
|
type="primary",
|
|
800
800
|
)
|
|
@@ -803,14 +803,14 @@ def _render_sidebar() -> dict:
|
|
|
803
803
|
with st.sidebar:
|
|
804
804
|
with st.spinner("Building graph (AST → SQLite)…"):
|
|
805
805
|
try:
|
|
806
|
-
from pycode_kg import ( #
|
|
806
|
+
from pycode_kg import ( # noqa: PLC0415
|
|
807
807
|
PyCodeKG,
|
|
808
808
|
)
|
|
809
809
|
|
|
810
810
|
kg = PyCodeKG(
|
|
811
811
|
repo_root=repo_root,
|
|
812
812
|
db_path=db_path,
|
|
813
|
-
|
|
813
|
+
vectors_path=vectors_path,
|
|
814
814
|
model=model,
|
|
815
815
|
)
|
|
816
816
|
if build_all_btn:
|
|
@@ -835,16 +835,16 @@ def _render_sidebar() -> dict:
|
|
|
835
835
|
|
|
836
836
|
if build_index_btn and not build_all_btn:
|
|
837
837
|
with st.sidebar:
|
|
838
|
-
with st.spinner("Building semantic index (SQLite →
|
|
838
|
+
with st.spinner("Building semantic index (SQLite → sqlite-vec)…"):
|
|
839
839
|
try:
|
|
840
|
-
from pycode_kg import ( #
|
|
840
|
+
from pycode_kg import ( # noqa: PLC0415
|
|
841
841
|
PyCodeKG,
|
|
842
842
|
)
|
|
843
843
|
|
|
844
844
|
kg = PyCodeKG(
|
|
845
845
|
repo_root=repo_root,
|
|
846
846
|
db_path=db_path,
|
|
847
|
-
|
|
847
|
+
vectors_path=vectors_path,
|
|
848
848
|
model=model,
|
|
849
849
|
)
|
|
850
850
|
stats = kg.build_index(wipe=True)
|
|
@@ -856,7 +856,7 @@ def _render_sidebar() -> dict:
|
|
|
856
856
|
return {
|
|
857
857
|
"db_path": db_path,
|
|
858
858
|
"repo_root": repo_root,
|
|
859
|
-
"
|
|
859
|
+
"vectors_path": vectors_path,
|
|
860
860
|
"model": model,
|
|
861
861
|
"k": k,
|
|
862
862
|
"hop": hop,
|
|
@@ -945,7 +945,7 @@ def _tab_graph(cfg: dict) -> None:
|
|
|
945
945
|
st.iframe(html, height=int(cfg["graph_height"].replace("px", "")))
|
|
946
946
|
|
|
947
947
|
with st.expander("📋 Node table"):
|
|
948
|
-
import pandas as pd #
|
|
948
|
+
import pandas as pd # noqa: PLC0415
|
|
949
949
|
|
|
950
950
|
df = pd.DataFrame(
|
|
951
951
|
[
|
|
@@ -984,7 +984,7 @@ def _tab_query(cfg: dict) -> None:
|
|
|
984
984
|
|
|
985
985
|
:param cfg: Configuration dictionary returned by ``_render_sidebar``,
|
|
986
986
|
providing keys such as ``store``, ``repo_root``, ``db_path``,
|
|
987
|
-
``
|
|
987
|
+
``vectors_path``, ``model``, ``k``, ``hop``, ``rels``,
|
|
988
988
|
``include_symbols``, ``graph_height``, and ``physics_on``.
|
|
989
989
|
"""
|
|
990
990
|
st.header("🔍 Hybrid Query")
|
|
@@ -1007,7 +1007,7 @@ def _tab_query(cfg: dict) -> None:
|
|
|
1007
1007
|
kg = _load_kg(
|
|
1008
1008
|
cfg["repo_root"],
|
|
1009
1009
|
cfg["db_path"],
|
|
1010
|
-
cfg["
|
|
1010
|
+
cfg["vectors_path"],
|
|
1011
1011
|
cfg["model"],
|
|
1012
1012
|
)
|
|
1013
1013
|
result = kg.query(
|
|
@@ -1052,7 +1052,7 @@ def _tab_query(cfg: dict) -> None:
|
|
|
1052
1052
|
st.info("No nodes to display.")
|
|
1053
1053
|
|
|
1054
1054
|
with tab_table:
|
|
1055
|
-
import pandas as pd #
|
|
1055
|
+
import pandas as pd # noqa: PLC0415
|
|
1056
1056
|
|
|
1057
1057
|
df = pd.DataFrame(
|
|
1058
1058
|
[
|
|
@@ -1075,7 +1075,7 @@ def _tab_query(cfg: dict) -> None:
|
|
|
1075
1075
|
|
|
1076
1076
|
with tab_edges:
|
|
1077
1077
|
if result.edges:
|
|
1078
|
-
import pandas as pd #
|
|
1078
|
+
import pandas as pd # noqa: PLC0415
|
|
1079
1079
|
|
|
1080
1080
|
edf = pd.DataFrame(
|
|
1081
1081
|
[
|
|
@@ -1119,7 +1119,7 @@ def _tab_snippets(cfg: dict) -> None:
|
|
|
1119
1119
|
|
|
1120
1120
|
:param cfg: Configuration dictionary returned by ``_render_sidebar``,
|
|
1121
1121
|
providing keys such as ``store``, ``repo_root``, ``db_path``,
|
|
1122
|
-
``
|
|
1122
|
+
``vectors_path``, ``model``, ``k``, ``hop``, ``rels``,
|
|
1123
1123
|
``include_symbols``, and ``physics_on``.
|
|
1124
1124
|
"""
|
|
1125
1125
|
st.header("📦 Snippet Pack")
|
|
@@ -1152,7 +1152,7 @@ def _tab_snippets(cfg: dict) -> None:
|
|
|
1152
1152
|
kg = _load_kg(
|
|
1153
1153
|
cfg["repo_root"],
|
|
1154
1154
|
cfg["db_path"],
|
|
1155
|
-
cfg["
|
|
1155
|
+
cfg["vectors_path"],
|
|
1156
1156
|
cfg["model"],
|
|
1157
1157
|
)
|
|
1158
1158
|
pack = kg.pack(
|
|
@@ -1249,7 +1249,7 @@ def _tab_snippets(cfg: dict) -> None:
|
|
|
1249
1249
|
# Edges table
|
|
1250
1250
|
if pack.edges:
|
|
1251
1251
|
with st.expander(f"🔗 Edges ({len(pack.edges)})"):
|
|
1252
|
-
import pandas as pd #
|
|
1252
|
+
import pandas as pd # noqa: PLC0415
|
|
1253
1253
|
|
|
1254
1254
|
edf = pd.DataFrame(
|
|
1255
1255
|
[
|
|
@@ -460,7 +460,7 @@ class ArchitectureAnalyzer:
|
|
|
460
460
|
"name": "Graph Query Pipeline",
|
|
461
461
|
"description": "Semantic search → graph expansion → snippet packing",
|
|
462
462
|
"steps": [
|
|
463
|
-
"Semantic search finds seed nodes via
|
|
463
|
+
"Semantic search finds seed nodes via sqlite-vec",
|
|
464
464
|
"Graph expansion traverses CALLS, CONTAINS, IMPORTS edges",
|
|
465
465
|
"Snippet pack materializes source code with context",
|
|
466
466
|
],
|
|
@@ -12,7 +12,7 @@ The root Click group is importable from either location::
|
|
|
12
12
|
from pycode_kg.cli import ( # noqa: F401 — registers snapshot (save, list, show, diff)
|
|
13
13
|
cmd_analyze, # noqa: F401 — registers analyze
|
|
14
14
|
cmd_architecture, # noqa: F401 — registers architecture
|
|
15
|
-
cmd_build, # noqa: F401 — registers build-sqlite, build-
|
|
15
|
+
cmd_build, # noqa: F401 — registers build-sqlite, build-index
|
|
16
16
|
cmd_build_full, # noqa: F401 — registers build (full pipeline), update (incremental upsert)
|
|
17
17
|
cmd_centrality, # noqa: F401 — registers centrality
|
|
18
18
|
cmd_explain, # noqa: F401 — registers explain
|
|
@@ -27,10 +27,10 @@ from pycode_kg.pycodekg_thorough_analysis import main as run_analysis
|
|
|
27
27
|
help="SQLite knowledge graph path (default: <repo>/.pycodekg/graph.sqlite).",
|
|
28
28
|
)
|
|
29
29
|
@click.option(
|
|
30
|
-
"--
|
|
30
|
+
"--vectors",
|
|
31
31
|
default=None,
|
|
32
32
|
type=click.Path(),
|
|
33
|
-
help="
|
|
33
|
+
help="sqlite-vec vector store path (default: <repo>/.pycodekg/vectors.sqlite).",
|
|
34
34
|
)
|
|
35
35
|
@click.option(
|
|
36
36
|
"--output",
|
|
@@ -63,7 +63,7 @@ from pycode_kg.pycodekg_thorough_analysis import main as run_analysis
|
|
|
63
63
|
def analyze(
|
|
64
64
|
repo_root: str,
|
|
65
65
|
db: str | None,
|
|
66
|
-
|
|
66
|
+
vectors: str | None,
|
|
67
67
|
output: str | None,
|
|
68
68
|
json_path: str | None,
|
|
69
69
|
quiet: bool,
|
|
@@ -86,7 +86,7 @@ def analyze(
|
|
|
86
86
|
run_analysis(
|
|
87
87
|
repo_root=repo_root,
|
|
88
88
|
db_path=db,
|
|
89
|
-
|
|
89
|
+
vectors_path=vectors,
|
|
90
90
|
report_path=output,
|
|
91
91
|
json_path=json_path,
|
|
92
92
|
quiet=quiet,
|