codegraph-engine 2.1.7__py3-none-any.whl → 2.2.0__py3-none-any.whl
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.
- codegraph/__init__.py +1 -1
- codegraph/cli.py +177 -54
- codegraph/cli_output.py +190 -0
- codegraph/context.py +119 -3
- codegraph/database/interrogation.py +30 -7
- codegraph/freshness.py +59 -21
- codegraph/indexing/indexer.py +11 -4
- codegraph/installer.py +72 -22
- codegraph/interrogation.py +19 -0
- codegraph/mcp/server.py +97 -6
- codegraph/mcp_diagnostics.py +5 -2
- codegraph/monorepo.py +1 -1
- codegraph/process_lifecycle.py +1115 -0
- codegraph/runtime/runner.py +204 -0
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/METADATA +48 -23
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/RECORD +20 -17
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/WHEEL +0 -0
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/entry_points.txt +0 -0
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {codegraph_engine-2.1.7.dist-info → codegraph_engine-2.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Zero-Friction Development Server Runtime Interceptor (v2.2.0).
|
|
2
|
+
|
|
3
|
+
Enables 1-line development telemetry capture:
|
|
4
|
+
codegraph run npm run dev
|
|
5
|
+
codegraph run uvicorn main:app
|
|
6
|
+
codegraph run python app.py
|
|
7
|
+
|
|
8
|
+
Security & Reliability Invariants:
|
|
9
|
+
- Passes stdin/stdout/stderr directly to the user's terminal with zero distortion.
|
|
10
|
+
- Strips authorization headers, cookies, and sensitive credentials via existing redaction rules.
|
|
11
|
+
- Streams captured HTTP requests and uncaught exceptions directly into `.codegraph/runtime.sqlite3`
|
|
12
|
+
without requiring code changes to the user's application.
|
|
13
|
+
- Cleans up child processes and temporary interceptor hooks on exit.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import subprocess
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
from codegraph.indexing import Indexer
|
|
25
|
+
from codegraph.runtime.ingestor import ingest_runtime_traces
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _generate_node_interceptor(output_jsonl: Path) -> str:
|
|
29
|
+
"""Generate lightweight Node.js HTTP/Express/Fastify request interceptor."""
|
|
30
|
+
escaped_log_path = json.dumps(str(output_jsonl))
|
|
31
|
+
return f"""// CodeGraph Node.js Runtime Interceptor
|
|
32
|
+
const http = require('http');
|
|
33
|
+
const https = require('https');
|
|
34
|
+
const fs = require('fs');
|
|
35
|
+
|
|
36
|
+
const logPath = {escaped_log_path};
|
|
37
|
+
|
|
38
|
+
function emitEvent(event) {{
|
|
39
|
+
try {{
|
|
40
|
+
fs.appendFileSync(logPath, JSON.stringify(event) + '\\n');
|
|
41
|
+
}} catch (_) {{}}
|
|
42
|
+
}}
|
|
43
|
+
|
|
44
|
+
function hookServer(serverProto) {{
|
|
45
|
+
const origEmit = serverProto.emit;
|
|
46
|
+
serverProto.emit = function(event, req, res) {{
|
|
47
|
+
if (event === 'request' && req && res) {{
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
const method = req.method || 'GET';
|
|
50
|
+
const url = req.url ? req.url.split('?')[0] : '/';
|
|
51
|
+
|
|
52
|
+
res.on('finish', () => {{
|
|
53
|
+
const duration = Date.now() - startTime;
|
|
54
|
+
emitEvent({{
|
|
55
|
+
trace_id: 'tr_' + Math.random().toString(36).substring(2, 10),
|
|
56
|
+
span_id: 'sp_' + Math.random().toString(36).substring(2, 10),
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
http_method: method,
|
|
59
|
+
route_path: url,
|
|
60
|
+
status_code: res.statusCode,
|
|
61
|
+
duration_ms: duration,
|
|
62
|
+
service_name: 'node_dev_server',
|
|
63
|
+
source_format: 'json'
|
|
64
|
+
}});
|
|
65
|
+
}});
|
|
66
|
+
}}
|
|
67
|
+
return origEmit.apply(this, arguments);
|
|
68
|
+
}};
|
|
69
|
+
}}
|
|
70
|
+
|
|
71
|
+
try {{
|
|
72
|
+
hookServer(http.Server.prototype);
|
|
73
|
+
}} catch (_) {{}}
|
|
74
|
+
|
|
75
|
+
process.on('uncaughtExceptionMonitor', (err) => {{
|
|
76
|
+
emitEvent({{
|
|
77
|
+
trace_id: 'err_' + Math.random().toString(36).substring(2, 10),
|
|
78
|
+
span_id: 'sp_err',
|
|
79
|
+
timestamp: new Date().toISOString(),
|
|
80
|
+
exception_type: (err && err.name) ? err.name : 'UncaughtException',
|
|
81
|
+
service_name: 'node_dev_server',
|
|
82
|
+
status_code: 500,
|
|
83
|
+
source_format: 'json'
|
|
84
|
+
}});
|
|
85
|
+
}});
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _generate_python_interceptor(output_jsonl: Path) -> str:
|
|
90
|
+
"""Generate lightweight Python WSGI/ASGI/FastAPI request interceptor."""
|
|
91
|
+
escaped_log_path = repr(str(output_jsonl))
|
|
92
|
+
return f"""# CodeGraph Python Runtime Interceptor
|
|
93
|
+
import sys
|
|
94
|
+
import json
|
|
95
|
+
import time
|
|
96
|
+
|
|
97
|
+
LOG_PATH = {escaped_log_path}
|
|
98
|
+
|
|
99
|
+
def emit_event(event):
|
|
100
|
+
try:
|
|
101
|
+
with open(LOG_PATH, "a", encoding="utf-8") as f:
|
|
102
|
+
f.write(json.dumps(event) + "\\n")
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
# Intercept uncaught exceptions
|
|
107
|
+
_orig_excepthook = sys.excepthook
|
|
108
|
+
def _cg_excepthook(exc_type, exc_value, exc_traceback):
|
|
109
|
+
emit_event({{
|
|
110
|
+
"trace_id": "err_" + str(int(time.time())),
|
|
111
|
+
"span_id": "sp_err",
|
|
112
|
+
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
113
|
+
"exception_type": getattr(exc_type, "__name__", "Exception"),
|
|
114
|
+
"service_name": "python_dev_server",
|
|
115
|
+
"status_code": 500,
|
|
116
|
+
"source_format": "json"
|
|
117
|
+
}})
|
|
118
|
+
return _orig_excepthook(exc_type, exc_value, exc_traceback)
|
|
119
|
+
|
|
120
|
+
sys.excepthook = _cg_excepthook
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def run_with_telemetry(
|
|
125
|
+
command: list[str],
|
|
126
|
+
repository: Path,
|
|
127
|
+
sample_rate: float = 1.0,
|
|
128
|
+
) -> int:
|
|
129
|
+
"""Execute a development command with transparent runtime trace capture."""
|
|
130
|
+
if not command:
|
|
131
|
+
raise ValueError("Command cannot be empty.")
|
|
132
|
+
|
|
133
|
+
hooks_dir = repository / ".codegraph" / "runtime_hooks"
|
|
134
|
+
hooks_dir.mkdir(parents=True, exist_ok=True)
|
|
135
|
+
trace_file = hooks_dir / "active_traces.jsonl"
|
|
136
|
+
# Ensure fresh trace buffer
|
|
137
|
+
if trace_file.exists():
|
|
138
|
+
try:
|
|
139
|
+
trace_file.unlink()
|
|
140
|
+
except OSError:
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
node_hook = hooks_dir / "cg_node_hook.js"
|
|
144
|
+
node_hook.write_text(_generate_node_interceptor(trace_file), encoding="utf-8")
|
|
145
|
+
|
|
146
|
+
python_hook = hooks_dir / "cg_python_hook.py"
|
|
147
|
+
python_hook.write_text(_generate_python_interceptor(trace_file), encoding="utf-8")
|
|
148
|
+
|
|
149
|
+
env = dict(os.environ)
|
|
150
|
+
|
|
151
|
+
# Inject Node hook
|
|
152
|
+
old_node_opts = env.get("NODE_OPTIONS", "")
|
|
153
|
+
env["NODE_OPTIONS"] = f"--require {node_hook} {old_node_opts}".strip()
|
|
154
|
+
|
|
155
|
+
# Inject Python hook
|
|
156
|
+
old_py_start = env.get("PYTHONSTARTUP", "")
|
|
157
|
+
if not old_py_start:
|
|
158
|
+
env["PYTHONSTARTUP"] = str(python_hook)
|
|
159
|
+
|
|
160
|
+
# Background ingestion thread
|
|
161
|
+
stop_event = threading.Event()
|
|
162
|
+
indexer = Indexer(repository)
|
|
163
|
+
|
|
164
|
+
def _ingest_loop() -> None:
|
|
165
|
+
last_pos = 0
|
|
166
|
+
while not stop_event.is_set():
|
|
167
|
+
time.sleep(1.0)
|
|
168
|
+
if not trace_file.exists():
|
|
169
|
+
continue
|
|
170
|
+
try:
|
|
171
|
+
size = trace_file.stat().st_size
|
|
172
|
+
if size > last_pos:
|
|
173
|
+
with open(trace_file, encoding="utf-8", errors="replace") as f:
|
|
174
|
+
f.seek(last_pos)
|
|
175
|
+
new_content = f.read()
|
|
176
|
+
last_pos = f.tell()
|
|
177
|
+
if new_content.strip():
|
|
178
|
+
with indexer.session() as con:
|
|
179
|
+
ingest_runtime_traces(con, new_content, repository=repository, max_events=1000, sampling_rate=sample_rate)
|
|
180
|
+
except Exception:
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
ingest_worker = threading.Thread(target=_ingest_loop, daemon=True)
|
|
184
|
+
ingest_worker.start()
|
|
185
|
+
|
|
186
|
+
# Spawn interactive dev process
|
|
187
|
+
try:
|
|
188
|
+
proc = subprocess.Popen(command, cwd=str(repository), env=env)
|
|
189
|
+
returncode = proc.wait()
|
|
190
|
+
except KeyboardInterrupt:
|
|
191
|
+
returncode = 0
|
|
192
|
+
finally:
|
|
193
|
+
stop_event.set()
|
|
194
|
+
# Drain remaining lines on shutdown
|
|
195
|
+
if trace_file.exists():
|
|
196
|
+
try:
|
|
197
|
+
content = trace_file.read_text(encoding="utf-8", errors="replace")
|
|
198
|
+
if content.strip():
|
|
199
|
+
with indexer.session() as con:
|
|
200
|
+
ingest_runtime_traces(con, content, repository=repository, max_events=1000, sampling_rate=sample_rate)
|
|
201
|
+
except Exception:
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
return returncode
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraph-engine
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Deep deterministic repository intelligence for AI coding agents (code, dependencies, databases, and runtime observations)
|
|
5
5
|
Author: CodeGraph contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,23 +35,24 @@ Dynamic: license-file
|
|
|
35
35
|
<img src="docs/assets/codegraph_logo.jpg" alt="CodeGraph MCP — Deep Deterministic Repository Intelligence for AI Coding Agents" width="500" />
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
|
-
<h1 align="center">CodeGraph Engine (v2.
|
|
38
|
+
<h1 align="center">CodeGraph-MCP Engine (v2.2.0)</h1>
|
|
39
39
|
|
|
40
40
|
<p align="center">
|
|
41
41
|
<strong>Deep deterministic repository intelligence for AI coding agents.</strong>
|
|
42
42
|
</p>
|
|
43
43
|
|
|
44
44
|
<p align="center">
|
|
45
|
-
<a href="https://
|
|
45
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><img src="https://img.shields.io/badge/pypi-codegraph--engine%20v2.2.0-blue.svg" alt="PyPI: codegraph-engine v2.2.0" /></a>
|
|
46
46
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.12%20%7C%203.13-3776AB.svg" alt="Python 3.12 | 3.13" /></a>
|
|
47
47
|
<a href="src/codegraph/mcp/server.py"><img src="https://img.shields.io/badge/MCP-14%20default%20%7C%2056%20full%20tools-2ea043.svg" alt="MCP Tools: 14 default | 56 full" /></a>
|
|
48
|
-
<a href="tests/"><img src="https://img.shields.io/badge/pytest-
|
|
48
|
+
<a href="tests/"><img src="https://img.shields.io/badge/pytest-861%20passed-brightgreen.svg" alt="Tests: 861 passed" /></a>
|
|
49
49
|
<a href="pyproject.toml"><img src="https://img.shields.io/badge/ruff-0%20errors-success.svg" alt="Ruff: 0 errors" /></a>
|
|
50
|
-
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(
|
|
50
|
+
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(80%20files)-blue.svg" alt="Mypy: strict" /></a>
|
|
51
51
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
52
52
|
</p>
|
|
53
53
|
|
|
54
54
|
<p align="center">
|
|
55
|
+
<a href="https://pypi.org/project/codegraph-engine/2.2.0/"><strong>PyPI (v2.2.0)</strong></a> •
|
|
55
56
|
<a href="#2-quickstart-30-second-setup"><strong>Quickstart</strong></a> •
|
|
56
57
|
<a href="#1-built-for-aiml-and-backend-heavy-repositories"><strong>Built For</strong></a> •
|
|
57
58
|
<a href="#5-database-intelligence"><strong>Database Intelligence</strong></a> •
|
|
@@ -125,7 +126,7 @@ pip install "codegraph-engine[mcp]"
|
|
|
125
126
|
|
|
126
127
|
### Step 2: Configure Your AI Coding Agents (`codegraph install`)
|
|
127
128
|
|
|
128
|
-
CodeGraph includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
129
|
+
CodeGraph-MCP includes an interactive, idempotent onboarding installer ([`src/codegraph/installer.py`](src/codegraph/installer.py)) that detects installed AI coding agents (**Claude Code**, **Cursor**, **Antigravity**, **Codex CLI**, **Gemini CLI**, and **Cline**), configures `mcpServers.codegraph`, installs marker-bounded routing instructions (`<!-- CODEGRAPH:START -->` … `<!-- CODEGRAPH:END -->`), and verifies MCP server startup:
|
|
129
130
|
|
|
130
131
|
```bash
|
|
131
132
|
# Interactive setup (detects installed agents, previews planned changes, asks confirmation)
|
|
@@ -147,18 +148,31 @@ codegraph status
|
|
|
147
148
|
codegraph doctor
|
|
148
149
|
```
|
|
149
150
|
|
|
150
|
-
|
|
151
|
+
> **Dynamic Index Hot-Reloading:** If your AI coding agent launches `codegraph mcp serve` before you run `codegraph init`, you do **not** need to restart your IDE or MCP session. As soon as `codegraph init` or `codegraph index` creates or updates `.codegraph.sqlite3`, the running MCP server automatically detects the updated database on the next tool call and refreshes its in-memory graph cache (`get_repository_status(reload=True, reindex=True)` can also be invoked directly by the agent).
|
|
151
152
|
|
|
152
|
-
|
|
153
|
+
### Managing Installation, Process & Project Index Lifecycle
|
|
154
|
+
|
|
155
|
+
CodeGraph cleanly separates agent configuration, process lifecycle, and project index files:
|
|
153
156
|
|
|
154
157
|
| Command | Scope | What It Does |
|
|
155
158
|
| :--- | :--- | :--- |
|
|
156
|
-
| `codegraph install` | Agent configuration | Configures MCP server + marker-managed rules/skills for selected AI agents. |
|
|
157
|
-
| `codegraph init` | Project repository | Initializes `.codegraph.sqlite3` and indexes the current repository. |
|
|
159
|
+
| `codegraph install` | Agent configuration | Configures MCP server + marker-managed rules/skills for selected AI agents (ASCII-safe on Windows `cp1252`). |
|
|
160
|
+
| `codegraph init` | Project repository | Initializes `.codegraph.sqlite3` and indexes the current repository (hot-reloaded automatically by running MCP servers). |
|
|
158
161
|
| `codegraph index` | Project repository | Incrementally indexes modified files (`--verbose`, `--quiet`, `--json`). |
|
|
159
|
-
| `codegraph
|
|
162
|
+
| `codegraph stop` | Process lifecycle | Safely stops running CodeGraph-owned MCP background processes (`--all`, `--repo`, `--json`) and releases file locks. |
|
|
163
|
+
| `codegraph doctor --processes` | Process lifecycle | Lists active CodeGraph MCP processes, parent PIDs, orphan status, and cleans stale PID files. |
|
|
164
|
+
| `codegraph uninstall` | Agent configuration | Stops active workspace MCP processes and removes CodeGraph-managed MCP entries and instruction blocks. |
|
|
160
165
|
| `codegraph uninit` | Project repository | Removes only `.codegraph.sqlite3` and `.codegraph/` in the project (never touches source code or Git history). |
|
|
161
166
|
|
|
167
|
+
### Safe Upgrading on Windows (`WinError 32` Prevention)
|
|
168
|
+
|
|
169
|
+
On Windows, running `pip install --upgrade codegraph-engine` while an IDE or agent still holds `codegraph.exe` open can trigger `WinError 32`. Before upgrading on Windows, run:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
codegraph stop --all
|
|
173
|
+
pip install --upgrade "codegraph-engine[mcp]"
|
|
174
|
+
```
|
|
175
|
+
|
|
162
176
|
---
|
|
163
177
|
|
|
164
178
|
## 3. Core Workflow & Architecture
|
|
@@ -218,7 +232,7 @@ InferenceService.run_inference
|
|
|
218
232
|
db:table:postgresql.public.prediction_logs
|
|
219
233
|
```
|
|
220
234
|
|
|
221
|
-
**What CodeGraph structurally proves**:
|
|
235
|
+
**What CodeGraph-MCP structurally proves**:
|
|
222
236
|
- `find_routes(path="/v1/predict")` resolves composed router prefixes (`MOUNTS`) to `predict_endpoint`.
|
|
223
237
|
- `trace_path(from_symbol="predict_endpoint", to_symbol="log_prediction")` proves the multi-hop execution chain across DI injection, preprocessing, model execution, and persistence.
|
|
224
238
|
- `get_db_impact(symbol="InferenceService.run_inference")` identifies downstream writes to `prediction_logs`.
|
|
@@ -236,7 +250,7 @@ TrainingPipeline.run
|
|
|
236
250
|
└──►CALLS (AST_VERIFIED) ──► Evaluator.compute_metrics
|
|
237
251
|
```
|
|
238
252
|
|
|
239
|
-
**What CodeGraph structurally proves**:
|
|
253
|
+
**What CodeGraph-MCP structurally proves**:
|
|
240
254
|
- `find_callees(symbol="TrainingPipeline.run")` enumerates every stage of the pipeline with exact file and line ranges.
|
|
241
255
|
- `find_tests(symbol="Evaluator.compute_metrics")` locates the unit and regression tests covering metric calculation.
|
|
242
256
|
- When a transform or model class is dynamically instantiated from a YAML string (`getattr(models, cfg.arch)`), CodeGraph explicitly records `POSSIBLE_CALLS` (`POSSIBLE`) or `UNRESOLVED_REFERENCE` (`UNKNOWN`) rather than fabricating a false static call edge.
|
|
@@ -255,7 +269,7 @@ AgentRunner.execute_step
|
|
|
255
269
|
└──►CALLS (AST_VERIFIED) ──► ModelProviderClient.generate
|
|
256
270
|
```
|
|
257
271
|
|
|
258
|
-
**What CodeGraph structurally proves**:
|
|
272
|
+
**What CodeGraph-MCP structurally proves**:
|
|
259
273
|
- Tracks decorator and call-based registrations (`@tool_registry.register("search_orders")`) via `REGISTERS` and `REGISTERED_HANDLER` edges.
|
|
260
274
|
- Tracks environment variable dependencies (`os.getenv("OPENAI_API_KEY")`) as `READS_ENV` edges with the variable name only—never indexing or exposing secret values.
|
|
261
275
|
|
|
@@ -419,20 +433,23 @@ Rather than claiming a single universal token reduction percentage across all po
|
|
|
419
433
|
| **Compression at `budget = 200 tokens`** | `85.6%` reduction | [`benchmarks/baselines/context_baseline.json`](benchmarks/baselines/context_baseline.json) |
|
|
420
434
|
| **Compression at `budget = 600 tokens`** | `56.3%` reduction | [`benchmarks/baselines/context_baseline.json`](benchmarks/baselines/context_baseline.json) |
|
|
421
435
|
| **Cold vs. Warm `get_context` Latency (`p50`)** | `20.0 ms` cold → `0.67 ms` warm (`30.0x`) | [`benchmarks/baselines/context_baseline.json`](benchmarks/baselines/context_baseline.json) |
|
|
436
|
+
| **Single-Tool Query Latency (Indexed SQLite)** | `1 ms – 15 ms` | Local SQLite B-tree / FTS5 lookup |
|
|
422
437
|
| **FACT / UNKNOWN / AMBIGUITY Correctness** | `100.0%` / `98.0%` / `100.0%` | [`benchmarks/baselines/v2_0_verified.json`](benchmarks/baselines/v2_0_verified.json) |
|
|
423
438
|
|
|
424
439
|
### Results from the 32-Task Internal Evaluation ([`src/codegraph/tool_selection_eval.py`](src/codegraph/tool_selection_eval.py))
|
|
425
440
|
|
|
426
|
-
The table below reports results from the **32-task internal evaluation harness** (`run_tool_selection_ab_benchmark()`) comparing Mode A (unassisted
|
|
441
|
+
The table below reports results from the **32-task internal evaluation harness** (`run_tool_selection_ab_benchmark()`) comparing Mode A (unassisted `grep` + full-file reading without CodeGraph routing rules) against Mode B (CodeGraph MCP + agent routing rules) on the same 32 tasks:
|
|
427
442
|
|
|
428
|
-
| Metric (32-Task Internal Evaluation) | Mode A (
|
|
443
|
+
| Metric (32-Task Internal Evaluation) | Mode A (Without CodeGraph) | Mode B (With CodeGraph MCP) | Measured Improvement |
|
|
429
444
|
| :--- | ---: | ---: | :--- |
|
|
430
|
-
| **Total Tool Calls** | `164` | `71` |
|
|
431
|
-
| **Direct Full-File Reads** | `161` | `7` |
|
|
432
|
-
| **
|
|
433
|
-
| **
|
|
434
|
-
| **
|
|
435
|
-
| **
|
|
445
|
+
| **Total Tool Calls (32 Tasks)** | `164 calls` (`~5.1 / task`) | `71 calls` (`~2.2 / task`) | **`-93 calls (-56.7% fewer tool calls)`** |
|
|
446
|
+
| **Direct Full-File Reads** | `161 full-file reads` | `7 bounded slice reads` | **`-154 file reads (-95.7% fewer file reads)`** |
|
|
447
|
+
| **Context Tokens per Task** | `3,000 – 12,000+ tokens` (full files) | `~542 tokens` avg (`get_context`) | **`65.0% – 85.6% token reduction`** |
|
|
448
|
+
| **Query Latency (`p50`)** | Hundreds of ms (multi-step `grep` + reads) | `20.0 ms` cold / `0.67 ms` warm (`30.0x`) | **Sub-20ms indexed lookup** |
|
|
449
|
+
| **First-Tool Selection Accuracy** | `9.38%` | `100.0%` | **`+90.62%`** |
|
|
450
|
+
| **Unsupported Claims (Hallucinated Edges)** | `11 (34.38%)` | `0 (0.00%)` | **`-11 claims (0% unsupported)`** |
|
|
451
|
+
| **Task Accuracy** | `59.84%` | `100.0%` | **`+40.16%`** |
|
|
452
|
+
| **12-Prompt Natural-Language Routing Eval** | — | `12 / 12 (100.0%)` | **`12/12 on this evaluation set`** |
|
|
436
453
|
|
|
437
454
|

|
|
438
455
|
|
|
@@ -540,6 +557,12 @@ codegraph index . --verbose # Incremental index w
|
|
|
540
557
|
codegraph index . --json # Output structured JSON phase telemetry
|
|
541
558
|
codegraph uninit --dry-run # Preview removal of .codegraph.sqlite3
|
|
542
559
|
|
|
560
|
+
# Process Lifecycle & Upgrade Lock Safety
|
|
561
|
+
codegraph stop # Safely stop CodeGraph MCP server for current repo
|
|
562
|
+
codegraph stop --all # Stop all CodeGraph-owned MCP processes across repos
|
|
563
|
+
codegraph stop --repo /path/to/repo --json # Stop MCP processes for a specific repo (JSON output)
|
|
564
|
+
codegraph doctor --processes # Inspect active MCP processes, parent PIDs, & stale locks
|
|
565
|
+
|
|
543
566
|
# Health, Integrity & Privacy Diagnostics
|
|
544
567
|
codegraph status . # Show index freshness and graph counts
|
|
545
568
|
codegraph doctor . --database --resources # Verify SQLite integrity, FKs, FTS, and memory
|
|
@@ -567,8 +590,10 @@ codegraph memory list -r . # Inspect repository-
|
|
|
567
590
|
codegraph benchmark -r . # Run deterministic benchmark suite
|
|
568
591
|
|
|
569
592
|
# MCP Server Subcommands
|
|
570
|
-
codegraph mcp serve . # Start stdio MCP server
|
|
593
|
+
codegraph mcp serve . # Start stdio MCP server (with parent/EOF lifecycle guard)
|
|
571
594
|
codegraph mcp serve . --profile full # Start stdio MCP server with all 56 tools
|
|
595
|
+
codegraph mcp stop # Alias for codegraph stop
|
|
596
|
+
codegraph mcp kill # Alias for codegraph stop (1s graceful timeout)
|
|
572
597
|
codegraph mcp doctor . # End-to-end MCP startup & query check
|
|
573
598
|
codegraph mcp config-check . # Read-only MCP config validation
|
|
574
599
|
codegraph mcp capabilities # Print machine-readable capability manifest
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
codegraph/__init__.py,sha256=
|
|
1
|
+
codegraph/__init__.py,sha256=4MtZhW_Qp2iqiJLUg-ypwlU6NAHaKg2XN-66U2K8aOM,845
|
|
2
2
|
codegraph/agent.py,sha256=We0TWEXSMBBz6t2NQEGPB6gv-2P1IwyCmxoFGPN_CBA,911
|
|
3
3
|
codegraph/agent_brain.py,sha256=xy0TWQsu4_xmuRlzrN-xbcLCBKcyTbwUAyW6PDW3FvI,130406
|
|
4
4
|
codegraph/agent_capabilities.py,sha256=Gub8wZ-CGOs0x8UUl-CALHMfBk4MJ9xifGIwtCnZT-w,180705
|
|
@@ -7,24 +7,26 @@ codegraph/architecture.py,sha256=8QAiAihwCJ_-jIBTUS4eEY1uk_TwpYh09hWRQc8sBjc,140
|
|
|
7
7
|
codegraph/audit.py,sha256=j6fFL6b4vKfnAdUYU7goqQBv4ysrxy-ecBJvT8rYoSI,3301
|
|
8
8
|
codegraph/binding_resolver.py,sha256=GgpXoUB2ue5vVF5LBoMAlXYk2ru1AHUhIynbq-y1afI,26569
|
|
9
9
|
codegraph/cache.py,sha256=42Fyl51EsMwcYDv5loosIicVvvrFnIw7JrqKJ7owZtw,2992
|
|
10
|
-
codegraph/cli.py,sha256=
|
|
10
|
+
codegraph/cli.py,sha256=LkodseN8BEiK-JVbOmCRI8EygZjgdN2kCtGBFiKX3QE,55121
|
|
11
|
+
codegraph/cli_output.py,sha256=HK83BQ9iAqQjE0LPUrMBube4N7sXU5T4Y-y3Otq0Hyw,5677
|
|
11
12
|
codegraph/config.py,sha256=8-LFxMfg84H77dcDhmsbJrLaB3g5lY_OiP77Qji2GK4,1975
|
|
12
13
|
codegraph/constraints.py,sha256=AR_d07ENmbcDhWmcbruy4DvBYXsEdvSwkatyQ6JO-dE,8554
|
|
13
|
-
codegraph/context.py,sha256=
|
|
14
|
+
codegraph/context.py,sha256=lXHZ0iPKuHVmmvMCBmZnqhoAf1L8hktAAFyUtuon9CQ,95413
|
|
14
15
|
codegraph/epistemic.py,sha256=xyGzFAHx8gtArVSrPLwSAN2PV20uUi1nUWtmgEKMS7Y,6051
|
|
15
16
|
codegraph/errors.py,sha256=QZk92Fr95qx-rfU3W5FVOEy1KjnKgtlbMykTnj4Rhos,10299
|
|
16
17
|
codegraph/evidence_contract.py,sha256=EYOcYeiCrdcmb7tQF8WkFUyz06iSTcUs5F-ssA4RFOA,22802
|
|
17
18
|
codegraph/frameworks.py,sha256=c5KIE8BlWvU4vAkKnuTZVtxwIOFxcYOlTQHEwnbIH-w,30143
|
|
18
|
-
codegraph/freshness.py,sha256=
|
|
19
|
+
codegraph/freshness.py,sha256=GIlva-vaugLBRUjvi6Eo9fQ36O5Lykgl6YBH0eqCudQ,12090
|
|
19
20
|
codegraph/git.py,sha256=q86cpC_HyEccnK2kuZcWMp-39gjSECs0D4Qbvq27P2A,12069
|
|
20
|
-
codegraph/installer.py,sha256=
|
|
21
|
-
codegraph/interrogation.py,sha256=
|
|
22
|
-
codegraph/mcp_diagnostics.py,sha256=
|
|
21
|
+
codegraph/installer.py,sha256=JwjOHWZv2oMYEjQ6vYIaAn_v94P-e-Ra0QcQWlLhhmo,66403
|
|
22
|
+
codegraph/interrogation.py,sha256=1_lSamzTo-KVtIfq6qH7jr4UiEgJAdpO__Bvsz95K8U,81687
|
|
23
|
+
codegraph/mcp_diagnostics.py,sha256=Am2Ad7OwBUPDxklHNk6XPTgBaba-_bi5q2mWYI-pVaE,33430
|
|
23
24
|
codegraph/models.py,sha256=OiIBQywI1D2MzUqFlQiSccoOenH_qfK9FP_JUl3Oh6A,6781
|
|
24
|
-
codegraph/monorepo.py,sha256=
|
|
25
|
+
codegraph/monorepo.py,sha256=ButoBATlZvkNPJxppYLJRh3UacqVt4WNNBQtImpG09Q,35404
|
|
25
26
|
codegraph/observability.py,sha256=zs0IuxCSVoNiwjqHkqGhb8_PpsA1QIftZamF_vOeAVI,9044
|
|
26
27
|
codegraph/optimizer.py,sha256=IicIRHQojHdFP0tEbpQORu9adoLshE6mueGaViIje1A,39243
|
|
27
28
|
codegraph/planner.py,sha256=p2wm5hSy5hYG5kdALX-o0R35jaOC9a7CKznPmt-GPA0,13790
|
|
29
|
+
codegraph/process_lifecycle.py,sha256=KeJcp7PnEJqJ3wr1RBKnpGikQ1jkuvXhbWUAr7WdThs,40598
|
|
28
30
|
codegraph/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
|
29
31
|
codegraph/query_expansion.py,sha256=KSTHHYPFsVJBvp09Wy6GICE6_JSCKzZ1JWaPE3pQ7fw,8224
|
|
30
32
|
codegraph/ranking.py,sha256=Zku5csLQ0_-9RmsYcdQUzTr5sDrHzNHRFQXtrFwleAc,16975
|
|
@@ -37,7 +39,7 @@ codegraph/task.py,sha256=dbku1uEfcBrrkY8bFCjoFMwRnTxa7oLxAfnTGzY5dTw,24740
|
|
|
37
39
|
codegraph/tool_selection_eval.py,sha256=2TWkhHqQ9KKEohM_gcX0k5LqymU9K2VZTPCuYbhZI10,48833
|
|
38
40
|
codegraph/database/__init__.py,sha256=OXSaeeAWw6fEn2mAJuVKjdaks_2Jx7JUhBE2YMBka3Q,1343
|
|
39
41
|
codegraph/database/extractor.py,sha256=mGFtkCcSc5D5l5xLy4XFPB-WMXNzFovRUaUUJ_qNi8Q,114833
|
|
40
|
-
codegraph/database/interrogation.py,sha256=
|
|
42
|
+
codegraph/database/interrogation.py,sha256=QmMhVkp_9YOo6wyOtcJ9_P04wPnQTGLmWwM7L5pfSJo,45017
|
|
41
43
|
codegraph/database/models.py,sha256=vgAlZdeR36-9DEUsIuXprt-38g_d7sdVUgS3eIBRbZc,11286
|
|
42
44
|
codegraph/evidence/__init__.py,sha256=f_KkJkf5pVoybqtpKqGqq8P4uu1F4xYj99vg-bmBrzE,268
|
|
43
45
|
codegraph/evidence/citations.py,sha256=VSgogkRibNZgJL4oBBl_SFSLjQv3EZm5KlxTeR3i-lg,14268
|
|
@@ -46,7 +48,7 @@ codegraph/graph/models.py,sha256=4-uTYEm6qXwyM_Rb1BRmOabNWwoC4muacMTu25AGiAQ,166
|
|
|
46
48
|
codegraph/graph/traversal.py,sha256=JdK6jDR6OgNvGsgzdJCRc_2GIyLsiqU8hXWPvLcjths,74580
|
|
47
49
|
codegraph/indexing/__init__.py,sha256=Pvj7M8zGmqGyjHG2gTI3pR_CthX4X3ztWrS2o2FZ7GA,446
|
|
48
50
|
codegraph/indexing/classifier.py,sha256=ocCVBXl411LStbyg3JFA8lm_UAD10xmwIDFDNzuJ408,16999
|
|
49
|
-
codegraph/indexing/indexer.py,sha256=
|
|
51
|
+
codegraph/indexing/indexer.py,sha256=_m9NvHL2ClfMFeOyXuOxJUnWg3_Uj5Caob_Nt5vb4bg,101598
|
|
50
52
|
codegraph/indexing/models.py,sha256=D4hBhi9fuoE7uFMBQgUiB2m0IK31SKlpufYwawmW_sU,14075
|
|
51
53
|
codegraph/indexing/parser.py,sha256=1OfNvzyLsoCM4Ehxdcr7X_hpI-dnYWAQ06G3XcnjROY,134875
|
|
52
54
|
codegraph/indexing/scanner.py,sha256=h85HdP0L0oasvBS1Um7Q6pnkmrP4JNVzONyxLtRzbC0,6448
|
|
@@ -56,7 +58,7 @@ codegraph/llm/__init__.py,sha256=rro4OuSOUFKhBq0-Rg-VAU7dvc6LS88YgdE8GfClb4E,89
|
|
|
56
58
|
codegraph/llm/base.py,sha256=M5f4mawPchXqlb7U7DF0cnGlDEy66KbuhhZc1hExZdU,406
|
|
57
59
|
codegraph/llm/context.py,sha256=TT5WIe3gTrvbQCASf2XDfyhwG3Cr5QPgqw9neXDM8qQ,641
|
|
58
60
|
codegraph/mcp/__init__.py,sha256=BmjrnksGkbG7TPqwbyQvgYj9uei8pFSFpfkRpaGVdJU,63
|
|
59
|
-
codegraph/mcp/server.py,sha256=
|
|
61
|
+
codegraph/mcp/server.py,sha256=He2ljWxfHuEVoGEmZ1A5OLjMjXvwvWRq5e-E1WlNQKc,62584
|
|
60
62
|
codegraph/memory/__init__.py,sha256=yfQgSZ9Tii6PPZiLW0ImwC2k-Bg6m7mnUm_K1laBems,58
|
|
61
63
|
codegraph/memory/store.py,sha256=K3iD9VWF5if4OmYCTb5KxtZ3zj45kfEKmz8yivWzP-M,1490
|
|
62
64
|
codegraph/resources/__init__.py,sha256=KPpsePEf6cNVvpMI4tnIbYVSw6Q77kaOP6wcmEko7tE,1296
|
|
@@ -70,15 +72,16 @@ codegraph/runtime/__init__.py,sha256=-h8VweOrbisugqbzTf69fVwZsJEXo7fThCa8Gk3DbRo
|
|
|
70
72
|
codegraph/runtime/ingestor.py,sha256=WP9y3esmJ_BKtbyALBHOJs2NLVpuGXR0sHjXJUB560s,27962
|
|
71
73
|
codegraph/runtime/models.py,sha256=BYDP3aSGCyLB7h3Y9QPn8qzc2RcRRTUsbx4qudeIG5s,4888
|
|
72
74
|
codegraph/runtime/reconciliation.py,sha256=ywd6uX8kA2nUjjmRFzqt5DgNymS7RlkGcv7LIAFnZfQ,21217
|
|
75
|
+
codegraph/runtime/runner.py,sha256=P1T0cxpO5PfxP_1JnNr6HfcT96AYWy-SKk4pnXj68eA,6631
|
|
73
76
|
codegraph/search/__init__.py,sha256=5TpuTZ1WtBSymowRftvv8SJ3C9VNG8HV-zreEHLQjjA,540
|
|
74
77
|
codegraph/search/hybrid.py,sha256=I9SQyvpgeA5ghTY7vVMqvXImiwWztl_EsYaXVpb-t4w,27580
|
|
75
78
|
codegraph/search/semantic.py,sha256=QZaJVEoOZIZrp4O6SmUAzMiqMPfopgmPSpqzL3T7GVg,836
|
|
76
79
|
codegraph/security/__init__.py,sha256=L1j4pRC4XTBgYk6e243MmpXskq5mHDwOpd9JHV_-0j8,1249
|
|
77
80
|
codegraph/security/paths.py,sha256=BPWbADXyuVCtCiqeZb8YSe4hYFTr-R-Gj1sYP4Jpy8M,5451
|
|
78
81
|
codegraph/security/redaction.py,sha256=CfkBYrFswybGw-g8IeKbW-qkZ5OXaHoSVynLGmGIh2Y,23371
|
|
79
|
-
codegraph_engine-2.
|
|
80
|
-
codegraph_engine-2.
|
|
81
|
-
codegraph_engine-2.
|
|
82
|
-
codegraph_engine-2.
|
|
83
|
-
codegraph_engine-2.
|
|
84
|
-
codegraph_engine-2.
|
|
82
|
+
codegraph_engine-2.2.0.dist-info/licenses/LICENSE,sha256=kMXNS9xyan1jJAG5_jORb8RyVeY-_Httz3JAtCjjyxI,1093
|
|
83
|
+
codegraph_engine-2.2.0.dist-info/METADATA,sha256=SvWxnyhadATQI3l_MQTn6oZvBRZ4MPNXaErX73NXI5E,45267
|
|
84
|
+
codegraph_engine-2.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
85
|
+
codegraph_engine-2.2.0.dist-info/entry_points.txt,sha256=U2xQ3yhqOaaDyFtV9p7N0FDref1VEk56RE_Bnvrnycc,48
|
|
86
|
+
codegraph_engine-2.2.0.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
|
|
87
|
+
codegraph_engine-2.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|