pycode-kg 0.19.3__tar.gz → 0.21.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/PKG-INFO +16 -19
  2. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/README.md +8 -7
  3. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/pyproject.toml +56 -47
  4. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/__init__.py +3 -3
  5. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/__init__.py +6 -0
  6. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/bridge.py +1 -1
  7. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/centrality.py +1 -1
  8. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/framework_detector.py +2 -2
  9. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/app.py +122 -394
  10. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/architecture.py +1 -1
  11. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/__init__.py +1 -1
  12. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_analyze.py +4 -4
  13. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_architecture.py +1 -1
  14. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_build.py +17 -21
  15. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_build_full.py +14 -24
  16. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_explain.py +4 -12
  17. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_hooks.py +11 -27
  18. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_init.py +4 -7
  19. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_mcp.py +8 -8
  20. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_model.py +2 -2
  21. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_query.py +9 -27
  22. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_snapshot.py +0 -1
  23. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_viz.py +109 -2
  24. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/options.py +6 -6
  25. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/explain.py +2 -8
  26. pycode_kg-0.21.0/src/pycode_kg/graph_html.py +131 -0
  27. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/kg.py +15 -17
  28. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/layout3d.py +6 -16
  29. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/mcp_server.py +55 -55
  30. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/__init__.py +1 -1
  31. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/extractor.py +2 -2
  32. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg.py +1 -1
  33. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_thorough_analysis.py +23 -23
  34. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/snapshots.py +1 -1
  35. pycode_kg-0.21.0/src/pycode_kg/theme.py +188 -0
  36. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/viz3d.py +93 -36
  37. pycode_kg-0.19.3/src/pycode_kg/build_pycodekg_lancedb.py +0 -15
  38. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/LICENSE +0 -0
  39. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/.DS_Store +0 -0
  40. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/__main__.py +0 -0
  41. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/analysis/hybrid_rank.py +0 -0
  42. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/build_pycodekg_sqlite.py +0 -0
  43. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_bridges.py +0 -0
  44. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_centrality.py +0 -0
  45. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/cmd_framework_nodes.py +0 -0
  46. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/cli/main.py +0 -0
  47. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/config.py +0 -0
  48. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/graph.py +0 -0
  49. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/index.py +0 -0
  50. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/base.py +0 -0
  51. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/module/types.py +0 -0
  52. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_query.py +0 -0
  53. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_snippet_packer.py +0 -0
  54. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_viz.py +0 -0
  55. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/pycodekg_viz3d.py +0 -0
  56. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/__init__.py +0 -0
  57. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/cli_rank.py +0 -0
  58. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/ranking/coderank.py +0 -0
  59. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/sql/004_add_centrality_table.sql +0 -0
  60. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/store.py +0 -0
  61. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/utils.py +0 -0
  62. {pycode_kg-0.19.3 → pycode_kg-0.21.0}/src/pycode_kg/visitor.py +0 -0
  63. {pycode_kg-0.19.3 → pycode_kg-0.21.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.19.3
3
+ Version: 0.21.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,lancedb,sqlite,semantic-search
7
+ Keywords: knowledge-graph,code-analysis,ast,sqlite-vec,sqlite,semantic-search
8
8
  Author: Eric G. Suchanek, PhD
9
- Author-email: suchanek@mac.com
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
@@ -17,7 +17,6 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Provides-Extra: all
19
19
  Provides-Extra: dev
20
- Provides-Extra: kgdeps
21
20
  Provides-Extra: viz
22
21
  Provides-Extra: viz3d
23
22
  Requires-Dist: PyQt5 (>=5.15.0) ; extra == "all"
@@ -25,12 +24,11 @@ Requires-Dist: PyQt5 (>=5.15.0) ; extra == "viz3d"
25
24
  Requires-Dist: click (>=8.1.0,<9)
26
25
  Requires-Dist: detect-secrets (>=1.5.0) ; extra == "all"
27
26
  Requires-Dist: detect-secrets (>=1.5.0) ; extra == "dev"
28
- Requires-Dist: doc-kg (>=0.15.2) ; extra == "dev"
29
- Requires-Dist: doc-kg (>=0.15.2) ; extra == "kgdeps"
30
- Requires-Dist: kgmodule-utils[semantic] (>=0.3.1)
27
+ Requires-Dist: kgmodule-utils[semantic,sqlite-vec,viz] (>=0.9.0)
31
28
  Requires-Dist: markdown (>=3.6) ; extra == "all"
32
29
  Requires-Dist: markdown (>=3.6) ; extra == "viz3d"
33
30
  Requires-Dist: mcp (>=1.0.0)
31
+ Requires-Dist: networkx (>=3.0)
34
32
  Requires-Dist: numpy (>=1.24.0)
35
33
  Requires-Dist: pandas (>=2.0.0)
36
34
  Requires-Dist: param (>=2.0.0) ; extra == "all"
@@ -41,8 +39,6 @@ Requires-Dist: plotly (>=5.14.0) ; extra == "all"
41
39
  Requires-Dist: plotly (>=5.14.0) ; extra == "viz"
42
40
  Requires-Dist: pre-commit (>=4.5.1) ; extra == "all"
43
41
  Requires-Dist: pre-commit (>=4.5.1) ; extra == "dev"
44
- Requires-Dist: pylint (>=4.0.5) ; extra == "all"
45
- Requires-Dist: pylint (>=4.0.5) ; extra == "dev"
46
42
  Requires-Dist: pytest (>=8.0.0) ; extra == "all"
47
43
  Requires-Dist: pytest (>=8.0.0) ; extra == "dev"
48
44
  Requires-Dist: pytest-cov (>=5.0.0) ; extra == "all"
@@ -58,12 +54,12 @@ Requires-Dist: ruff (>=0.4.0) ; extra == "all"
58
54
  Requires-Dist: ruff (>=0.4.0) ; extra == "dev"
59
55
  Requires-Dist: safetensors (>=0.5.0)
60
56
  Requires-Dist: sentence-transformers (>=5.4.1)
61
- Requires-Dist: streamlit (>=1.35.0) ; extra == "all"
62
- Requires-Dist: streamlit (>=1.35.0) ; extra == "viz"
57
+ Requires-Dist: streamlit (>=1.56.0) ; extra == "all"
58
+ Requires-Dist: streamlit (>=1.56.0) ; extra == "viz"
63
59
  Requires-Dist: torch (>=2.5.1)
64
60
  Requires-Dist: trame-vtk (>=2.0.0) ; extra == "all"
65
61
  Requires-Dist: trame-vtk (>=2.0.0) ; extra == "viz3d"
66
- Requires-Dist: transformers (>=4.40.0,<4.57)
62
+ Requires-Dist: transformers (>=5.5.0,<6)
67
63
  Requires-Dist: ty (>=0.0.41) ; extra == "all"
68
64
  Requires-Dist: ty (>=0.0.41) ; extra == "dev"
69
65
  Project-URL: Homepage, https://github.com/Flux-Frontiers/pycode_kg
@@ -77,7 +73,7 @@ Description-Content-Type: text/markdown
77
73
 
78
74
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
79
75
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
80
- [![Version](https://img.shields.io/badge/version-0.19.3-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
76
+ [![Version](https://img.shields.io/badge/version-0.21.0-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
81
77
  [![CI](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
82
78
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
83
79
  [![DOI](https://zenodo.org/badge/1202379010.svg)](https://zenodo.org/badge/latestdoi/1202379010)
@@ -86,7 +82,7 @@ Description-Content-Type: text/markdown
86
82
 
87
83
  **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
84
 
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 LanceDB 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.
85
+ 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
86
 
91
87
  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
88
 
@@ -197,7 +193,7 @@ That's the recommended path. Variants (minimal install, MCP-only, contributor se
197
193
 
198
194
  Search is hybrid by design. A query like *"authentication flow"* runs in two phases:
199
195
 
200
- 1. **Vector phase** — the query is embedded with a local sentence-transformer (cached after first download) and LanceDB returns the `k` closest functions, classes, and modules by cosine similarity.
196
+ 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
197
  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
198
 
203
199
  **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.
@@ -217,6 +213,7 @@ The graph is built around four node kinds (module, class, function, method) and
217
213
  | **Pull source-grounded context for an LLM** | `pycodekg pack "..." --format md` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
218
214
  | **Run a hybrid semantic + structural query** | `pycodekg query "..."` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
219
215
  | **Browse the graph interactively** | `pycodekg viz` (Streamlit) | [docs/INSTALLATION.md](docs/INSTALLATION.md) |
216
+ | **Share a graph as one file** | `pycodekg viz-export -o graph.html` | opens from `file://`, no server |
220
217
  | **See call graphs in 3-D** *(active development — functional but rough)* | `pycodekg viz3d --layout funnel` | [docs/VIZ3D.md](docs/VIZ3D.md) |
221
218
  | **Wire it into Claude / Copilot / Cline** | `pycodekg mcp` | [docs/MCP.md](docs/MCP.md) |
222
219
 
@@ -231,7 +228,7 @@ src/pycode_kg/
231
228
  ├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
232
229
  ├── graph.py # GraphBuilder: file discovery + dispatch
233
230
  ├── store.py # SQLite persistence + canonical edges
234
- ├── index.py # LanceDB semantic index
231
+ ├── index.py # sqlite-vec semantic index
235
232
  ├── pycodekg.py # Public façade
236
233
  ├── pycodekg_query.py # Hybrid query
237
234
  ├── pycodekg_snippet_packer.py # Source-grounded packs
@@ -273,13 +270,13 @@ If you use PyCodeKG in your research or project, please cite it:
273
270
 
274
271
  [![DOI](https://zenodo.org/badge/1202379010.svg)](https://zenodo.org/badge/latestdoi/1202379010)
275
272
 
276
- > Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.19.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
273
+ > Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.21.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
277
274
 
278
275
  ```bibtex
279
276
  @software{suchanek_pycode_kg,
280
277
  author = {Suchanek, Eric G.},
281
278
  title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
282
- version = {0.19.0},
279
+ version = {0.21.0},
283
280
  year = {2026},
284
281
  publisher = {Flux-Frontiers},
285
282
  url = {https://github.com/Flux-Frontiers/pycode_kg},
@@ -299,7 +296,7 @@ If you use PyCodeKG in your research or project, please cite it:
299
296
 
300
297
  - **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
301
298
  - Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
302
- - LanceDB, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
299
+ - sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
303
300
 
304
301
  ---
305
302
 
@@ -5,7 +5,7 @@
5
5
 
6
6
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
7
7
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
8
- [![Version](https://img.shields.io/badge/version-0.19.3-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
8
+ [![Version](https://img.shields.io/badge/version-0.21.0-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
9
9
  [![CI](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml/badge.svg)](https://github.com/Flux-Frontiers/pycode_kg/actions/workflows/ci.yml)
10
10
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
11
11
  [![DOI](https://zenodo.org/badge/1202379010.svg)](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 LanceDB 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.
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 LanceDB returns the `k` closest functions, classes, and modules by cosine similarity.
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.
@@ -145,6 +145,7 @@ The graph is built around four node kinds (module, class, function, method) and
145
145
  | **Pull source-grounded context for an LLM** | `pycodekg pack "..." --format md` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
146
146
  | **Run a hybrid semantic + structural query** | `pycodekg query "..."` | [docs/CHEATSHEET.md](docs/CHEATSHEET.md) |
147
147
  | **Browse the graph interactively** | `pycodekg viz` (Streamlit) | [docs/INSTALLATION.md](docs/INSTALLATION.md) |
148
+ | **Share a graph as one file** | `pycodekg viz-export -o graph.html` | opens from `file://`, no server |
148
149
  | **See call graphs in 3-D** *(active development — functional but rough)* | `pycodekg viz3d --layout funnel` | [docs/VIZ3D.md](docs/VIZ3D.md) |
149
150
  | **Wire it into Claude / Copilot / Cline** | `pycodekg mcp` | [docs/MCP.md](docs/MCP.md) |
150
151
 
@@ -159,7 +160,7 @@ src/pycode_kg/
159
160
  ├── visitor.py # AST extraction (three-pass: structure, calls, dataflow)
160
161
  ├── graph.py # GraphBuilder: file discovery + dispatch
161
162
  ├── store.py # SQLite persistence + canonical edges
162
- ├── index.py # LanceDB semantic index
163
+ ├── index.py # sqlite-vec semantic index
163
164
  ├── pycodekg.py # Public façade
164
165
  ├── pycodekg_query.py # Hybrid query
165
166
  ├── pycodekg_snippet_packer.py # Source-grounded packs
@@ -201,13 +202,13 @@ If you use PyCodeKG in your research or project, please cite it:
201
202
 
202
203
  [![DOI](https://zenodo.org/badge/1202379010.svg)](https://zenodo.org/badge/latestdoi/1202379010)
203
204
 
204
- > Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.19.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
205
+ > Suchanek, E. G. (2026). *PyCodeKG: A Knowledge Graph for Python Codebases* (Version 0.21.0) [Software]. Flux-Frontiers. https://doi.org/10.5281/zenodo.19834777
205
206
 
206
207
  ```bibtex
207
208
  @software{suchanek_pycode_kg,
208
209
  author = {Suchanek, Eric G.},
209
210
  title = {{PyCodeKG}: A Knowledge Graph for Python Codebases},
210
- version = {0.19.0},
211
+ version = {0.21.0},
211
212
  year = {2026},
212
213
  publisher = {Flux-Frontiers},
213
214
  url = {https://github.com/Flux-Frontiers/pycode_kg},
@@ -227,7 +228,7 @@ If you use PyCodeKG in your research or project, please cite it:
227
228
 
228
229
  - **Issues** — [GitHub Issues](https://github.com/Flux-Frontiers/pycode_kg/issues)
229
230
  - Sister projects [DocKG](https://github.com/Flux-Frontiers/doc_kg) and [MetaboKG](https://github.com/Flux-Frontiers/metabo_kg)
230
- - LanceDB, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
231
+ - sqlite-vec, sentence-transformers, PyVista, Streamlit, and FastMCP for the foundations
231
232
 
232
233
  ---
233
234
 
@@ -1,7 +1,7 @@
1
1
  # pyproject.toml — PyCodeKG package configuration (PEP 621)
2
2
  #
3
3
  # Author: Eric G. Suchanek, PhD
4
- # Last Revision: 2026-04-24
4
+ # Last Revision: 2026-07-28
5
5
  #
6
6
  # Build system : Poetry 2.x with PEP 621 [project] table
7
7
  #
@@ -10,7 +10,6 @@
10
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
- # pip install -e ".[kgdeps]" core + KG integrations (doc-kg, agent-kg)
14
13
  # pip install -e ".[all]" everything above
15
14
  # pip install -e "." core runtime only
16
15
  #
@@ -20,7 +19,6 @@
20
19
  # poetry install --extras "dev" core + dev tools only
21
20
  # poetry install --extras "viz" core + Streamlit/Plotly visualizer only
22
21
  # poetry install --extras "viz3d" core + 3D visualizer only
23
- # poetry install --extras "kgdeps" core + KG integrations only
24
22
  # poetry install core runtime only
25
23
  #
26
24
  # First-time setup
@@ -46,29 +44,40 @@ build-backend = "poetry.core.masonry.api"
46
44
  [tool.poetry]
47
45
  packages = [{ include = "pycode_kg", from = "src" }]
48
46
 
49
- [tool.poetry.group.dev.dependencies]
50
- detect-secrets = ">=1.5.0"
51
- ty = "^0.0.41"
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"
47
+ # CPU-only torch on Linux: dev/CI here has no GPU, but the default PyPI linux
48
+ # wheel bundles the full CUDA runtime (~2.7G of nvidia-* packages, ~700M of
49
+ # triton) regardless. "explicit" priority means only packages naming this
50
+ # source use it — nothing else is redirected off PyPI. This affects local/CI
51
+ # installs only; it is not part of published wheel metadata, so `pip install
52
+ # pycode-kg` for a GPU user still resolves torch normally.
53
+ #
54
+ # Linux only: macOS/Windows torch builds are already CPU/MPS, and this index
55
+ # publishes the macOS ones without the "+cpu" local version label, so locking
56
+ # it globally leaves those platforms with no installable candidate.
57
+ [[tool.poetry.source]]
58
+ name = "pytorch-cpu"
59
+ url = "https://download.pytorch.org/whl/cpu"
60
+ priority = "explicit"
61
+
62
+ [tool.poetry.dependencies]
63
+ torch = [
64
+ { markers = "sys_platform == 'linux'", source = "pytorch-cpu" },
65
+ { markers = "sys_platform != 'linux'" },
66
+ ]
58
67
 
59
68
  # ---------------------------------------------------------------------------
60
69
  # PEP 621 project metadata
61
70
  # ---------------------------------------------------------------------------
62
71
  [project]
63
72
  name = "pycode-kg"
64
- version = "0.19.3"
73
+ version = "0.21.0"
65
74
  description = "A tool to build a searchable knowledge graph from Python repositories"
66
75
  readme = "README.md"
67
76
  license = "Elastic-2.0"
68
77
  authors = [
69
- { name = "Eric G. Suchanek, PhD", email = "suchanek@mac.com" }
78
+ { name = "Eric G. Suchanek, PhD", email = "suchanek@flux-frontiers.com" }
70
79
  ]
71
- keywords = ["knowledge-graph", "code-analysis", "ast", "lancedb", "sqlite", "semantic-search"]
80
+ keywords = ["knowledge-graph", "code-analysis", "ast", "sqlite-vec", "sqlite", "semantic-search"]
72
81
  classifiers = [
73
82
  "Development Status :: 4 - Beta",
74
83
  "Intended Audience :: Developers",
@@ -82,14 +91,15 @@ requires-python = ">=3.12,<3.14"
82
91
  dependencies = [
83
92
  "click>=8.1.0,<9",
84
93
  "mcp>=1.0.0",
94
+ "networkx>=3.0",
85
95
  "numpy>=1.24.0",
86
96
  "pandas>=2.0.0",
87
97
  "rich>=14.3.3,<15",
88
98
  "safetensors>=0.5.0",
89
99
  "sentence-transformers>=5.4.1",
90
100
  "torch>=2.5.1",
91
- "transformers>=4.40.0,<4.57",
92
- "kgmodule-utils[semantic]>=0.3.1",
101
+ "transformers>=5.5.0,<6",
102
+ "kgmodule-utils[semantic,sqlite-vec,viz]>=0.9.0",
93
103
  ]
94
104
 
95
105
  [project.optional-dependencies]
@@ -98,17 +108,14 @@ dev = [
98
108
  "ty>=0.0.41",
99
109
  "pdoc>=14.0.0",
100
110
  "pre-commit>=4.5.1",
101
- "pylint>=4.0.5",
102
111
  "pytest>=8.0.0",
103
112
  "pytest-cov>=5.0.0",
104
113
  "ruff>=0.4.0",
105
- "doc-kg>=0.15.2",
106
- # agent-kg not yet on PyPI — install manually: pip install git+https://github.com/Flux-Frontiers/agent_kg.git
107
114
  ]
108
115
  viz = [
109
116
  "plotly>=5.14.0",
110
117
  "pyvis>=0.3.2",
111
- "streamlit>=1.35.0",
118
+ "streamlit>=1.56.0",
112
119
  ]
113
120
  viz3d = [
114
121
  "markdown>=3.6",
@@ -119,10 +126,14 @@ viz3d = [
119
126
  "trame-vtk>=2.0.0",
120
127
  ]
121
128
 
122
- # note that dockg is on pypi; agent-kg is not yet — install manually from git
123
- kgdeps = [
124
- "doc-kg>=0.15.2",
125
- ]
129
+ # Cross-KG sibling packages (doc-kg, pycode-kg, agent-kg, kg-rag) are NOT
130
+ # declared here. They are never imported by this package, and listing them
131
+ # forces poetry's universal resolution to reconcile the transformers pin of
132
+ # every *published* sibling against this project's own -- a deadlock, since
133
+ # doc-kg and pycode-kg each depend on the other. Install them by hand:
134
+ # pip install doc-kg pycode-kg # both on PyPI
135
+ # pip install 'kg-rag @ git+https://github.com/Flux-Frontiers/KGRAG.git'
136
+ # pip install 'agent-kg @ git+https://github.com/Flux-Frontiers/agent_kg.git'
126
137
  all = [
127
138
  "detect-secrets>=1.5.0",
128
139
  "markdown>=3.6",
@@ -130,7 +141,6 @@ all = [
130
141
  "pdoc>=14.0.0",
131
142
  "plotly>=5.14.0",
132
143
  "pre-commit>=4.5.1",
133
- "pylint>=4.0.5",
134
144
  "PyQt5>=5.15.0",
135
145
  "pytest>=8.0.0",
136
146
  "pytest-cov>=5.0.0",
@@ -138,7 +148,7 @@ all = [
138
148
  "pyvistaqt>=0.11.0",
139
149
  "pyvis>=0.3.2",
140
150
  "ruff>=0.4.0",
141
- "streamlit>=1.35.0",
151
+ "streamlit>=1.56.0",
142
152
  "trame-vtk>=2.0.0",
143
153
  "ty>=0.0.41",
144
154
  ]
@@ -152,7 +162,7 @@ pycodekg = "pycode_kg.cli.main:cli"
152
162
  pycodekg-analyze = "pycode_kg.cli.cmd_analyze:analyze"
153
163
  pycodekg-architecture = "pycode_kg.cli.cmd_architecture:architecture"
154
164
  pycodekg-build = "pycode_kg.cli.cmd_build_full:build"
155
- pycodekg-build-lancedb = "pycode_kg.cli.cmd_build:build_lancedb"
165
+ pycodekg-build-index = "pycode_kg.cli.cmd_build:build_index"
156
166
  pycodekg-build-sqlite = "pycode_kg.cli.cmd_build:build_sqlite"
157
167
  pycodekg-centrality = "pycode_kg.cli.cmd_centrality:cmd_centrality"
158
168
  pycodekg-download-model = "pycode_kg.cli.cmd_model:download_model"
@@ -172,11 +182,24 @@ pycodekg-viz3d = "pycode_kg.cli.cmd_viz:viz3d"
172
182
  [tool.ruff]
173
183
  line-length = 100
174
184
  target-version = "py312"
185
+ # Vendored agent scratch dirs (Claude Code skills, Codex) — not project code.
186
+ # The pre-commit hook's exclude can't cover these (it runs with
187
+ # pass_filenames: false), so the exclusion must live here.
188
+ extend-exclude = [".claude", ".agents", ".codex"]
175
189
 
176
190
  [tool.ruff.lint]
177
- select = ["E", "F", "W", "I", "UP"]
191
+ # B023, BLE001, PLC0415 replace the retired pylint hook's cell-var-from-loop,
192
+ # broad-exception-caught, and import-outside-toplevel checks.
193
+ select = ["E", "F", "W", "I", "UP", "B023", "BLE001", "PLC0415"]
178
194
  ignore = ["E501"]
179
195
 
196
+ [tool.ruff.lint.per-file-ignores]
197
+ # viz3d is GUI code full of deliberate lazy imports (optional Qt/pyvista deps).
198
+ "src/pycode_kg/viz3d.py" = ["PLC0415"]
199
+ # Test imports are often deliberately lazy — they must run after sys.modules
200
+ # mocks are installed.
201
+ "tests/**" = ["PLC0415"]
202
+
180
203
  [tool.ty.environment]
181
204
  python-version = "3.12"
182
205
  root = ["src"]
@@ -192,28 +215,14 @@ unresolved-import = "ignore"
192
215
  unused-ignore-comment = "ignore"
193
216
 
194
217
  [tool.pytest.ini_options]
195
- testpaths = ["tests"]
196
- addopts = "-v --tb=short"
218
+ testpaths = ["tests"]
219
+ addopts = "-v --tb=short"
220
+ pythonpath = ["src"]
197
221
  markers = [
198
222
  "slow: marks tests as slow (deselect with '-m not slow')",
199
- "integration: marks tests that exercise real external dependencies (model, LanceDB)",
223
+ "integration: marks tests that exercise real external dependencies (model, sqlite-vec)",
200
224
  ]
201
225
 
202
- [tool.pylint.messages_control]
203
- disable = ["all"]
204
- enable = [
205
- "broad-exception-caught", # W0718
206
- "cell-var-from-loop", # W0640
207
- "cyclic-import", # R0401
208
- "import-outside-toplevel", # C0415
209
- "undefined-variable", # E0602
210
- ]
211
-
212
- [tool.pylint.imports]
213
- # The kg → pycodekg_thorough_analysis cycle is broken at runtime by a lazy
214
- # import inside PyCodeKG.analyze(). Pylint's static analysis can't see that.
215
- ignored-modules = ["pycode_kg.pycodekg_thorough_analysis"]
216
-
217
226
  # ---------------------------------------------------------------------------
218
227
  # PyCodeKG / DocKG index configuration
219
228
  # ---------------------------------------------------------------------------
@@ -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) → LanceDB (semantic index).
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, lancedb_dir)
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.19.3"
35
+ __version__ = "0.21.0"
36
36
  __author__ = "Eric G. Suchanek, PhD"
37
37
 
38
38
  # Low-level primitives (locked v0 contract)
@@ -1,5 +1,7 @@
1
1
  """Analysis primitives for PyCodeKG."""
2
2
 
3
+ from kg_utils.analysis.scores import MetricRef, ScoreSet, available_metrics, load_scores
4
+
3
5
  from .centrality import (
4
6
  CentralityConfig,
5
7
  CentralityRecord,
@@ -10,6 +12,10 @@ from .centrality import (
10
12
  __all__ = [
11
13
  "CentralityConfig",
12
14
  "CentralityRecord",
15
+ "MetricRef",
16
+ "ScoreSet",
13
17
  "StructuralImportanceRanker",
14
18
  "aggregate_module_scores",
19
+ "available_metrics",
20
+ "load_scores",
15
21
  ]
@@ -4,7 +4,7 @@ Measures module interaction complexity: how many unique modules each module call
4
4
  For well-modularized codebases, identifies orchestrator and hub modules.
5
5
 
6
6
  Author: Eric G. Suchanek, PhD
7
- Last Revision: 2026-03-12 17:30:35
7
+ Last Revision: 2026-04-27 23:29:23
8
8
  License: Elastic 2.0
9
9
  """
10
10
 
@@ -12,7 +12,7 @@ Public API:
12
12
  - :func:`aggregate_module_scores` — roll node scores up to module level.
13
13
 
14
14
  Author: Eric G. Suchanek, PhD
15
- Last Revision: 2026-03-11 12:45:30
15
+ Last Revision: 2026-05-01 21:46:11
16
16
  """
17
17
 
18
18
  from __future__ import annotations
@@ -3,7 +3,7 @@ Framework Detector for PyCodeKG.
3
3
  Identifies repo-defining abstractions using centrality and cross-module signals.
4
4
 
5
5
  Author: Eric G. Suchanek, PhD
6
- Last Revision: 2026-03-12 17:30:35
6
+ Last Revision: 2026-07-15 22:51:18
7
7
  License: Elastic 2.0
8
8
  """
9
9
 
@@ -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 ( # pylint: disable=import-outside-toplevel
65
+ from pycode_kg.analysis.centrality import ( # noqa: PLC0415
66
66
  StructuralImportanceRanker,
67
67
  aggregate_module_scores,
68
68
  )