pycode-kg 0.18.1__tar.gz → 0.18.2__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 (62) hide show
  1. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/PKG-INFO +21 -35
  2. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/README.md +20 -34
  3. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/pyproject.toml +1 -1
  4. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/__init__.py +1 -1
  5. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/analysis/centrality.py +21 -0
  6. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_bridges.py +1 -0
  7. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_framework_nodes.py +1 -0
  8. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/ranking/cli_rank.py +2 -0
  9. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/snapshots.py +12 -0
  10. pycode_kg-0.18.1/src/pycode_kg/mcp/bridge_tools.py +0 -19
  11. pycode_kg-0.18.1/src/pycode_kg/mcp/framework_tools.py +0 -18
  12. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/LICENSE +0 -0
  13. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/.DS_Store +0 -0
  14. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/__main__.py +0 -0
  15. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/analysis/__init__.py +0 -0
  16. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/analysis/bridge.py +0 -0
  17. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/analysis/framework_detector.py +0 -0
  18. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/analysis/hybrid_rank.py +0 -0
  19. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/app.py +0 -0
  20. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/architecture.py +0 -0
  21. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/build_pycodekg_lancedb.py +0 -0
  22. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/build_pycodekg_sqlite.py +0 -0
  23. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/__init__.py +0 -0
  24. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_analyze.py +0 -0
  25. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_architecture.py +0 -0
  26. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_build.py +0 -0
  27. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_build_full.py +0 -0
  28. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_centrality.py +0 -0
  29. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_explain.py +0 -0
  30. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_hooks.py +0 -0
  31. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_init.py +0 -0
  32. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_mcp.py +0 -0
  33. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_model.py +0 -0
  34. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_query.py +0 -0
  35. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_snapshot.py +0 -0
  36. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/cmd_viz.py +0 -0
  37. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/main.py +0 -0
  38. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/cli/options.py +0 -0
  39. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/config.py +0 -0
  40. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/graph.py +0 -0
  41. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/index.py +0 -0
  42. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/kg.py +0 -0
  43. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/layout3d.py +0 -0
  44. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/mcp_server.py +0 -0
  45. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/module/__init__.py +0 -0
  46. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/module/base.py +0 -0
  47. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/module/extractor.py +0 -0
  48. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/module/types.py +0 -0
  49. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg.py +0 -0
  50. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg_query.py +0 -0
  51. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg_snippet_packer.py +0 -0
  52. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg_thorough_analysis.py +0 -0
  53. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg_viz.py +0 -0
  54. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/pycodekg_viz3d.py +0 -0
  55. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/ranking/__init__.py +0 -0
  56. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/ranking/coderank.py +0 -0
  57. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/sql/004_add_centrality_table.sql +0 -0
  58. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/store.py +0 -0
  59. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/utils.py +0 -0
  60. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/visitor.py +0 -0
  61. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/viz3d.py +0 -0
  62. {pycode_kg-0.18.1 → pycode_kg-0.18.2}/src/pycode_kg/viz3d_timeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycode-kg
3
- Version: 0.18.1
3
+ Version: 0.18.2
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
@@ -78,7 +78,7 @@ Description-Content-Type: text/markdown
78
78
 
79
79
  [![Python](https://img.shields.io/badge/python-3.12%20%7C%203.13-blue.svg)](https://www.python.org/)
80
80
  [![License: Elastic-2.0](https://img.shields.io/badge/License-Elastic%202.0-blue.svg)](https://www.elastic.co/licensing/elastic-license)
81
- [![Version](https://img.shields.io/badge/version-0.18.1-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
81
+ [![Version](https://img.shields.io/badge/version-0.18.2-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
82
82
  [![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)
83
83
  [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
84
84
  [![DOI](https://zenodo.org/badge/1202379010.svg)](https://zenodo.org/badge/latestdoi/1202379010)
@@ -114,31 +114,13 @@ PyCodeKG uses the same architecture as [DocKG](https://github.com/Flux-Frontiers
114
114
  - **Source-grounded snippet packing** — Definition and call-site snippets with line numbers
115
115
  - **Precise fan-in lookup** — Two-phase reverse traversal resolving cross-module caller chains
116
116
  - **Temporal snapshots** — Save and diff graph metrics across commits and versions
117
- - **MCP server** — Seventeen tools for AI agent integration
117
+ - **MCP server** — Nineteen tools for AI agent integration
118
118
  - **Streamlit web app** — Interactive graph browser, hybrid query UI, snippet pack explorer
119
119
  - **3-D visualizer** — PyVista/PyQt5 interactive graph explorer with FunnelLayout and timeline view
120
120
  - **Zero-config MCP setup** — Single-line installer configures Claude Code, Kilo Code, GitHub Copilot, and Cline
121
121
 
122
122
  ---
123
123
 
124
- ## Quick Start
125
-
126
- ```bash
127
- # Index your repo (SQLite + LanceDB in one step)
128
- pycodekg build --repo /path/to/repo
129
-
130
- # Natural-language query
131
- pycodekg query "authentication flow"
132
-
133
- # Source-grounded snippet pack — paste straight into an LLM prompt
134
- pycodekg pack "database connection setup" --format md --out context.md
135
-
136
- # Full architectural analysis
137
- pycodekg analyze /path/to/repo
138
- ```
139
-
140
- ---
141
-
142
124
  ## Installation
143
125
 
144
126
  **Requirements:** Python ≥ 3.12, < 3.14
@@ -161,6 +143,24 @@ poetry add pycode-kg
161
143
 
162
144
  ---
163
145
 
146
+ ## Quick Start
147
+
148
+ ```bash
149
+ # Index your repo (SQLite + LanceDB in one step)
150
+ pycodekg build --repo /path/to/repo
151
+
152
+ # Natural-language query
153
+ pycodekg query "authentication flow"
154
+
155
+ # Source-grounded snippet pack — paste straight into an LLM prompt
156
+ pycodekg pack "database connection setup" --format md --out context.md
157
+
158
+ # Full architectural analysis
159
+ pycodekg analyze /path/to/repo
160
+ ```
161
+
162
+ ---
163
+
164
164
  ## Usage
165
165
 
166
166
  ### Build and query
@@ -198,20 +198,6 @@ pycodekg viz-timeline # metric history timeline
198
198
 
199
199
  ---
200
200
 
201
- ## MCP Integration
202
-
203
- Start the MCP server, then wire it into your AI agent:
204
-
205
- ```bash
206
- pycodekg mcp --repo /path/to/repo
207
- ```
208
-
209
- PyCodeKG exposes seventeen tools covering hybrid search, snippet packing, caller tracing, architectural analysis, and temporal snapshots. Any MCP-compatible agent — Claude Code, Claude Desktop, Cursor, Continue, GitHub Copilot — can consume them directly.
210
-
211
- > Full provider setup, tool reference, and SSE transport: [docs/MCP.md](docs/MCP.md)
212
-
213
- ---
214
-
215
201
  ## What Agents Say
216
202
 
217
203
  *From independent assessments run against PyCodeKG's own codebase. See [assessments/](assessments/) for full reports.*
@@ -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.18.1-blue.svg)](https://github.com/Flux-Frontiers/pycode_kg/releases)
8
+ [![Version](https://img.shields.io/badge/version-0.18.2-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)
@@ -41,31 +41,13 @@ PyCodeKG uses the same architecture as [DocKG](https://github.com/Flux-Frontiers
41
41
  - **Source-grounded snippet packing** — Definition and call-site snippets with line numbers
42
42
  - **Precise fan-in lookup** — Two-phase reverse traversal resolving cross-module caller chains
43
43
  - **Temporal snapshots** — Save and diff graph metrics across commits and versions
44
- - **MCP server** — Seventeen tools for AI agent integration
44
+ - **MCP server** — Nineteen tools for AI agent integration
45
45
  - **Streamlit web app** — Interactive graph browser, hybrid query UI, snippet pack explorer
46
46
  - **3-D visualizer** — PyVista/PyQt5 interactive graph explorer with FunnelLayout and timeline view
47
47
  - **Zero-config MCP setup** — Single-line installer configures Claude Code, Kilo Code, GitHub Copilot, and Cline
48
48
 
49
49
  ---
50
50
 
51
- ## Quick Start
52
-
53
- ```bash
54
- # Index your repo (SQLite + LanceDB in one step)
55
- pycodekg build --repo /path/to/repo
56
-
57
- # Natural-language query
58
- pycodekg query "authentication flow"
59
-
60
- # Source-grounded snippet pack — paste straight into an LLM prompt
61
- pycodekg pack "database connection setup" --format md --out context.md
62
-
63
- # Full architectural analysis
64
- pycodekg analyze /path/to/repo
65
- ```
66
-
67
- ---
68
-
69
51
  ## Installation
70
52
 
71
53
  **Requirements:** Python ≥ 3.12, < 3.14
@@ -88,6 +70,24 @@ poetry add pycode-kg
88
70
 
89
71
  ---
90
72
 
73
+ ## Quick Start
74
+
75
+ ```bash
76
+ # Index your repo (SQLite + LanceDB in one step)
77
+ pycodekg build --repo /path/to/repo
78
+
79
+ # Natural-language query
80
+ pycodekg query "authentication flow"
81
+
82
+ # Source-grounded snippet pack — paste straight into an LLM prompt
83
+ pycodekg pack "database connection setup" --format md --out context.md
84
+
85
+ # Full architectural analysis
86
+ pycodekg analyze /path/to/repo
87
+ ```
88
+
89
+ ---
90
+
91
91
  ## Usage
92
92
 
93
93
  ### Build and query
@@ -125,20 +125,6 @@ pycodekg viz-timeline # metric history timeline
125
125
 
126
126
  ---
127
127
 
128
- ## MCP Integration
129
-
130
- Start the MCP server, then wire it into your AI agent:
131
-
132
- ```bash
133
- pycodekg mcp --repo /path/to/repo
134
- ```
135
-
136
- PyCodeKG exposes seventeen tools covering hybrid search, snippet packing, caller tracing, architectural analysis, and temporal snapshots. Any MCP-compatible agent — Claude Code, Claude Desktop, Cursor, Continue, GitHub Copilot — can consume them directly.
137
-
138
- > Full provider setup, tool reference, and SSE transport: [docs/MCP.md](docs/MCP.md)
139
-
140
- ---
141
-
142
128
  ## What Agents Say
143
129
 
144
130
  *From independent assessments run against PyCodeKG's own codebase. See [assessments/](assessments/) for full reports.*
@@ -66,7 +66,7 @@ ruff = ">=0.4.0"
66
66
  # ---------------------------------------------------------------------------
67
67
  [project]
68
68
  name = "pycode-kg"
69
- version = "0.18.1"
69
+ version = "0.18.2"
70
70
  description = "A tool to build a searchable knowledge graph from Python repositories"
71
71
  readme = "README.md"
72
72
  license = "Elastic-2.0"
@@ -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.18.1"
35
+ __version__ = "0.18.2"
36
36
  __author__ = "Eric G. Suchanek, PhD"
37
37
 
38
38
  # Low-level primitives (locked v0 contract)
@@ -112,6 +112,13 @@ class StructuralImportanceRanker:
112
112
  """
113
113
 
114
114
  def __init__(self, db_path: str | Path, config: CentralityConfig | None = None) -> None:
115
+ """Bind the ranker to a SQLite graph and (optional) tuning config.
116
+
117
+ :param db_path: Path to the PyCodeKG SQLite knowledge graph.
118
+ :param config: Override default relation weights, damping, iteration
119
+ cap, tolerance, cross-module boost, or private-symbol penalty.
120
+ Pass ``None`` for the package defaults (see ``CentralityConfig``).
121
+ """
115
122
  self.db_path = Path(db_path)
116
123
  self.config = config or CentralityConfig()
117
124
 
@@ -204,6 +211,7 @@ class StructuralImportanceRanker:
204
211
  return len(rows)
205
212
 
206
213
  def _load_nodes(self) -> dict[str, _NodeInfo]:
214
+ """Load real graph nodes (modules, classes, functions, methods) from SQLite, keyed by node id. ``sym:`` stubs are excluded."""
207
215
  with sqlite3.connect(self.db_path) as con:
208
216
  rows = con.execute(
209
217
  """
@@ -221,6 +229,11 @@ class StructuralImportanceRanker:
221
229
  self,
222
230
  node_map: dict[str, _NodeInfo],
223
231
  ) -> list[_EffectiveEdge]:
232
+ """Load structural edges (CALLS / INHERITS / IMPORTS / CONTAINS) and rewrite ``sym:`` targets through ``RESOLVES_TO``.
233
+
234
+ Returns deduplicated edges weighted by relation type, with cross-module
235
+ edges receiving an additional boost from ``config.cross_module_boost``.
236
+ """
224
237
  with sqlite3.connect(self.db_path) as con:
225
238
  structural = con.execute(
226
239
  """
@@ -280,6 +293,13 @@ class StructuralImportanceRanker:
280
293
  node_map: dict[str, _NodeInfo],
281
294
  effective_edges: list[_EffectiveEdge],
282
295
  ) -> dict[str, float]:
296
+ """Run weighted PageRank on the resolved edge set until convergence.
297
+
298
+ Iterates up to ``config.max_iter`` with damping ``config.damping``,
299
+ redistributing dangling-node mass uniformly. After convergence, names
300
+ starting with ``_`` are scaled by ``config.private_penalty`` and the
301
+ result is normalized so all scores sum to ``1.0``.
302
+ """
283
303
  nodes = list(node_map)
284
304
  n = len(nodes)
285
305
  if n == 0:
@@ -329,6 +349,7 @@ class StructuralImportanceRanker:
329
349
  effective_edges: list[_EffectiveEdge],
330
350
  scores: dict[str, float],
331
351
  ) -> list[CentralityRecord]:
352
+ """Combine PageRank scores with inbound counts, per-relation breakdowns, and top contributing callers into rank-ordered ``CentralityRecord`` outputs."""
332
353
  inbound_counts: dict[str, int] = defaultdict(int)
333
354
  cross_counts: dict[str, int] = defaultdict(int)
334
355
  rel_breakdown: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
@@ -8,6 +8,7 @@ from pycode_kg.analysis.bridge import compute_bridge_centrality
8
8
 
9
9
 
10
10
  def main():
11
+ """CLI entry point: parse args and print top bridge modules by connectivity score to stdout."""
11
12
  parser = argparse.ArgumentParser(
12
13
  description="Show top bridge modules by betweenness centrality."
13
14
  )
@@ -8,6 +8,7 @@ from pycode_kg.analysis.framework_detector import detect_framework_nodes
8
8
 
9
9
 
10
10
  def main():
11
+ """CLI entry point: parse args and print top framework-like modules (high SIR + high connectivity) to stdout."""
11
12
  parser = argparse.ArgumentParser(description="Show top framework-like modules.")
12
13
  parser.add_argument("--db", default="pycodekg.sqlite", help="Path to PyCodeKG SQLite DB")
13
14
  parser.add_argument("--top", type=int, default=25, help="Number of top framework nodes to show")
@@ -16,6 +16,7 @@ from .coderank import (
16
16
 
17
17
 
18
18
  def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
19
+ """Parse CodeRank CLI arguments. Pass ``argv`` to override ``sys.argv`` (used in tests)."""
19
20
  parser = argparse.ArgumentParser(description="Compute CodeRank metrics for PyCodeKG graphs.")
20
21
  parser.add_argument("--sqlite", required=True, help="Path to PyCodeKG SQLite graph.")
21
22
  parser.add_argument("--top", type=int, default=25, help="Number of top results to print.")
@@ -43,6 +44,7 @@ def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
43
44
 
44
45
 
45
46
  def main(argv: Sequence[str] | None = None) -> int:
47
+ """CLI entry point: compute CodeRank scores, optionally persist them to ``node_metrics``, and print the top results as plain text or JSON. Returns the process exit code."""
46
48
  args = parse_args(argv)
47
49
  sqlite_path = Path(args.sqlite)
48
50
  if not sqlite_path.exists():
@@ -269,6 +269,15 @@ class SnapshotManager(_BaseSnapshotManager):
269
269
  db_path: Path | str | None = None,
270
270
  package_name: str = "pycode-kg",
271
271
  ) -> None:
272
+ """Initialize the manager rooted at ``snapshots_dir``.
273
+
274
+ :param snapshots_dir: Directory where snapshot JSON files live; created
275
+ on first save if it does not exist.
276
+ :param db_path: PyCodeKG SQLite graph path; required for collecting
277
+ per-module node counts during ``capture()``. Optional otherwise.
278
+ :param package_name: Package name used for version detection in saved
279
+ snapshots. Defaults to ``"pycode-kg"``.
280
+ """
272
281
  super().__init__(snapshots_dir, package_name=package_name, db_path=db_path)
273
282
 
274
283
  # ------------------------------------------------------------------
@@ -457,14 +466,17 @@ class SnapshotManager(_BaseSnapshotManager):
457
466
  # ------------------------------------------------------------------
458
467
 
459
468
  def load_snapshot(self, key: str) -> Snapshot | None: # type: ignore[override]
469
+ """Load a snapshot by key and re-wrap it as a pycode-kg ``Snapshot`` with typed-accessor properties. Returns ``None`` if no snapshot matches."""
460
470
  snap = super().load_snapshot(key)
461
471
  return _rewrap(snap) if snap is not None else None
462
472
 
463
473
  def get_previous(self, key: str) -> Snapshot | None: # type: ignore[override]
474
+ """Return the snapshot immediately preceding ``key`` in manifest chronology, re-wrapped as a pycode-kg ``Snapshot``. ``None`` when ``key`` is the earliest."""
464
475
  snap = super().get_previous(key)
465
476
  return _rewrap(snap) if snap is not None else None
466
477
 
467
478
  def get_baseline(self) -> Snapshot | None: # type: ignore[override]
479
+ """Return the earliest (baseline) snapshot in the manifest, re-wrapped as a pycode-kg ``Snapshot``. ``None`` if no snapshots exist."""
468
480
  snap = super().get_baseline()
469
481
  return _rewrap(snap) if snap is not None else None
470
482
 
@@ -1,19 +0,0 @@
1
- """
2
- MCP tool hooks for bridge centrality in PyCodeKG.
3
- """
4
-
5
- # Placeholder for MCP integration
6
-
7
-
8
- def top_bridges(kind="module", limit=20):
9
- from pycode_kg.analysis.bridge import ( # pylint: disable=import-outside-toplevel
10
- compute_bridge_centrality,
11
- )
12
-
13
- bridges = compute_bridge_centrality(kind=kind, top=limit)
14
- return bridges
15
-
16
-
17
- def why_bridge(node_id):
18
- # TODO: Explain why a node is a bridge
19
- pass
@@ -1,18 +0,0 @@
1
- """
2
- MCP tool hooks for framework node detection in PyCodeKG.
3
- """
4
-
5
- # Placeholder for MCP integration
6
-
7
-
8
- def detect_framework_nodes(limit=20):
9
- from pycode_kg.analysis.framework_detector import ( # pylint: disable=import-outside-toplevel
10
- detect_framework_nodes as detect_fw,
11
- )
12
-
13
- return detect_fw(limit=limit)
14
-
15
-
16
- def why_framework_node(node_id):
17
- # TODO: Explain why a node is a framework node
18
- pass
File without changes