codegraph-engine 2.2.1__py3-none-any.whl → 2.3.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/agent_capabilities.py +245 -4
- codegraph/branch_comparison.py +197 -0
- codegraph/change_impact.py +337 -0
- codegraph/cli.py +238 -0
- codegraph/context_freshness.py +349 -0
- codegraph/git_state.py +543 -0
- codegraph/mcp/server.py +69 -0
- codegraph/semantic_conflicts.py +270 -0
- codegraph/structural_diff.py +540 -0
- codegraph/symbol_history.py +275 -0
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/METADATA +126 -20
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/RECORD +17 -10
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/WHEEL +0 -0
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/entry_points.txt +0 -0
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/licenses/LICENSE +0 -0
- {codegraph_engine-2.2.1.dist-info → codegraph_engine-2.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Deterministic Symbol History Engine.
|
|
2
|
+
|
|
3
|
+
Traces the evolutionary history of a symbol across Git commits:
|
|
4
|
+
- Symbol introduced / added
|
|
5
|
+
- Symbol modified (signature, body, docstring)
|
|
6
|
+
- Symbol renamed (tracked via AST structure & body hashes)
|
|
7
|
+
- Symbol moved across files (tracked via Git renames and structural equality)
|
|
8
|
+
- Symbol deleted
|
|
9
|
+
|
|
10
|
+
Epistemic states:
|
|
11
|
+
- FACT: Exact body hash match, canonical ID continuity, or Git rename (-M) metadata
|
|
12
|
+
- POSSIBLE: Structural or signature similarity without identical body hash
|
|
13
|
+
- AMBIGUOUS: Multiple candidate replacements detected
|
|
14
|
+
- UNKNOWN: Disappeared with no identifiable successor
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import hashlib
|
|
19
|
+
import sqlite3
|
|
20
|
+
import subprocess
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
from codegraph.git import recent_commits
|
|
26
|
+
from codegraph.indexing.parser import parse
|
|
27
|
+
from codegraph.indexing.scanner import LANGUAGES
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class SymbolHistoryEvent:
|
|
32
|
+
commit_sha: str
|
|
33
|
+
date: str
|
|
34
|
+
author: str
|
|
35
|
+
message: str
|
|
36
|
+
event_type: str # "INTRODUCED" | "MODIFIED" | "RENAMED" | "MOVED" | "DELETED"
|
|
37
|
+
path: str
|
|
38
|
+
old_path: str | None = None
|
|
39
|
+
old_name: str | None = None
|
|
40
|
+
new_name: str | None = None
|
|
41
|
+
confidence: str = "FACT" # "FACT" | "POSSIBLE" | "AMBIGUOUS" | "UNKNOWN"
|
|
42
|
+
evidence: str = ""
|
|
43
|
+
|
|
44
|
+
def as_dict(self) -> dict[str, Any]:
|
|
45
|
+
return {
|
|
46
|
+
"commit_sha": self.commit_sha,
|
|
47
|
+
"date": self.date,
|
|
48
|
+
"author": self.author,
|
|
49
|
+
"message": self.message,
|
|
50
|
+
"event_type": self.event_type,
|
|
51
|
+
"path": self.path,
|
|
52
|
+
"old_path": self.old_path,
|
|
53
|
+
"old_name": self.old_name,
|
|
54
|
+
"new_name": self.new_name,
|
|
55
|
+
"confidence": self.confidence,
|
|
56
|
+
"evidence": self.evidence,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass
|
|
61
|
+
class SymbolHistoryReport:
|
|
62
|
+
symbol: str
|
|
63
|
+
current_path: str | None
|
|
64
|
+
events: list[SymbolHistoryEvent] = field(default_factory=list)
|
|
65
|
+
total_commits_evaluated: int = 0
|
|
66
|
+
status: str = "SUCCESS" # "SUCCESS" | "NOT_FOUND" | "AMBIGUOUS"
|
|
67
|
+
detail: str = ""
|
|
68
|
+
|
|
69
|
+
def as_dict(self) -> dict[str, Any]:
|
|
70
|
+
return {
|
|
71
|
+
"symbol": self.symbol,
|
|
72
|
+
"current_path": self.current_path,
|
|
73
|
+
"events": [e.as_dict() for e in self.events],
|
|
74
|
+
"total_commits_evaluated": self.total_commits_evaluated,
|
|
75
|
+
"status": self.status,
|
|
76
|
+
"detail": self.detail,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _run_git(repository: Path, *args: str, timeout: int = 15) -> str | None:
|
|
81
|
+
for arg in args:
|
|
82
|
+
if any(c in arg for c in (";", "|", "&", "`", "$", "\n", "\r")):
|
|
83
|
+
return None
|
|
84
|
+
try:
|
|
85
|
+
res = subprocess.run(
|
|
86
|
+
["git", *args],
|
|
87
|
+
cwd=str(repository),
|
|
88
|
+
capture_output=True,
|
|
89
|
+
text=True,
|
|
90
|
+
timeout=timeout,
|
|
91
|
+
)
|
|
92
|
+
return res.stdout if res.returncode == 0 else None
|
|
93
|
+
except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
_BODY_HASH_CACHE: dict[tuple[int, str, str, str], tuple[str | None, int | None]] = {}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _get_symbol_body_hash(content: str, lang: str, file_path: str, symbol_name: str) -> tuple[str | None, int | None]:
|
|
101
|
+
"""Parse content and compute content hash for symbol body with caching."""
|
|
102
|
+
if not content:
|
|
103
|
+
return None, None
|
|
104
|
+
c_hash = hash(content)
|
|
105
|
+
cache_key = (c_hash, lang, file_path, symbol_name)
|
|
106
|
+
if cache_key in _BODY_HASH_CACHE:
|
|
107
|
+
return _BODY_HASH_CACHE[cache_key]
|
|
108
|
+
try:
|
|
109
|
+
res = parse(content, lang, file_path)
|
|
110
|
+
for s in res.symbols:
|
|
111
|
+
if s.name == symbol_name:
|
|
112
|
+
lines = content.splitlines()
|
|
113
|
+
snippet = "\n".join(lines[max(0, s.start_line - 1) : s.end_line]).strip()
|
|
114
|
+
b_hash = hashlib.sha256(snippet.encode("utf-8", errors="replace")).hexdigest()[:16]
|
|
115
|
+
result = (b_hash, s.start_line)
|
|
116
|
+
if len(_BODY_HASH_CACHE) > 2000:
|
|
117
|
+
_BODY_HASH_CACHE.clear()
|
|
118
|
+
_BODY_HASH_CACHE[cache_key] = result
|
|
119
|
+
return result
|
|
120
|
+
_BODY_HASH_CACHE[cache_key] = (None, None)
|
|
121
|
+
return None, None
|
|
122
|
+
except Exception:
|
|
123
|
+
return None, None
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def trace_symbol_history(
|
|
127
|
+
repository: Path,
|
|
128
|
+
symbol: str,
|
|
129
|
+
path: str | None = None,
|
|
130
|
+
con: sqlite3.Connection | None = None,
|
|
131
|
+
max_commits: int = 15,
|
|
132
|
+
) -> SymbolHistoryReport:
|
|
133
|
+
"""Trace the history of a symbol across Git commits deterministically."""
|
|
134
|
+
from codegraph.structural_diff import _get_file_content_at_ref
|
|
135
|
+
|
|
136
|
+
# 1. Resolve path if not provided
|
|
137
|
+
resolved_path = path
|
|
138
|
+
if not resolved_path and con is not None:
|
|
139
|
+
try:
|
|
140
|
+
row = con.execute("SELECT path FROM symbols WHERE name=? LIMIT 1", (symbol,)).fetchone()
|
|
141
|
+
if row:
|
|
142
|
+
resolved_path = str(row[0])
|
|
143
|
+
except (sqlite3.OperationalError, sqlite3.DatabaseError):
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# 2. Get commits affecting the file or symbol
|
|
147
|
+
commits = recent_commits(repository, n=max_commits * 2, path=resolved_path)
|
|
148
|
+
if not commits:
|
|
149
|
+
return SymbolHistoryReport(
|
|
150
|
+
symbol=symbol,
|
|
151
|
+
current_path=resolved_path,
|
|
152
|
+
events=[],
|
|
153
|
+
total_commits_evaluated=0,
|
|
154
|
+
status="NOT_FOUND",
|
|
155
|
+
detail=f"No Git commits found for symbol '{symbol}' or path '{resolved_path}'.",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
events: list[SymbolHistoryEvent] = []
|
|
159
|
+
current_sym_name = symbol
|
|
160
|
+
current_sym_path = resolved_path or ""
|
|
161
|
+
|
|
162
|
+
prev_parent_content: str | None = None
|
|
163
|
+
prev_parent_hash: str | None = None
|
|
164
|
+
prev_parent_line: int | None = None
|
|
165
|
+
prev_parent_path: str | None = None
|
|
166
|
+
|
|
167
|
+
for c in commits:
|
|
168
|
+
if len(events) >= max_commits:
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
ext = Path(current_sym_path).suffix.lower() if current_sym_path else ".py"
|
|
172
|
+
lang = LANGUAGES.get(ext, "python")
|
|
173
|
+
|
|
174
|
+
# Fast path: check if curr_content was already loaded as parent in previous iteration
|
|
175
|
+
curr_content: str | None = None
|
|
176
|
+
curr_hash: str | None = None
|
|
177
|
+
curr_line: int | None = None
|
|
178
|
+
|
|
179
|
+
if prev_parent_content is not None and prev_parent_path == current_sym_path:
|
|
180
|
+
curr_content = prev_parent_content
|
|
181
|
+
curr_hash, curr_line = prev_parent_hash, prev_parent_line
|
|
182
|
+
else:
|
|
183
|
+
curr_content = _get_file_content_at_ref(repository, c.sha, current_sym_path) if current_sym_path else None
|
|
184
|
+
curr_hash, curr_line = _get_symbol_body_hash(curr_content or "", lang, current_sym_path, current_sym_name) if curr_content else (None, None)
|
|
185
|
+
|
|
186
|
+
# Get file content at parent commit c.sha~1
|
|
187
|
+
parent_content = _get_file_content_at_ref(repository, f"{c.sha}~1", current_sym_path) if current_sym_path else None
|
|
188
|
+
parent_hash, parent_line = _get_symbol_body_hash(parent_content or "", lang, current_sym_path, current_sym_name) if parent_content else (None, None)
|
|
189
|
+
|
|
190
|
+
# Store for next iteration
|
|
191
|
+
prev_parent_content = parent_content
|
|
192
|
+
prev_parent_hash = parent_hash
|
|
193
|
+
prev_parent_line = parent_line
|
|
194
|
+
prev_parent_path = current_sym_path
|
|
195
|
+
|
|
196
|
+
if curr_hash is not None and parent_hash is not None:
|
|
197
|
+
if curr_hash != parent_hash:
|
|
198
|
+
events.append(
|
|
199
|
+
SymbolHistoryEvent(
|
|
200
|
+
commit_sha=c.sha,
|
|
201
|
+
date=c.date,
|
|
202
|
+
author=c.author,
|
|
203
|
+
message=c.message,
|
|
204
|
+
event_type="MODIFIED",
|
|
205
|
+
path=current_sym_path,
|
|
206
|
+
confidence="FACT",
|
|
207
|
+
evidence=f"Symbol modified at line {curr_line} (body hash changed)",
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
elif curr_hash is not None and parent_hash is None:
|
|
211
|
+
# Symbol appeared in this commit! Did it rename or move from somewhere else?
|
|
212
|
+
found_move = False
|
|
213
|
+
# Check git diff --name-status c.sha~1 c.sha for renames
|
|
214
|
+
raw_rename = _run_git(repository, "diff", "-M", "--name-status", f"{c.sha}~1", c.sha)
|
|
215
|
+
if raw_rename:
|
|
216
|
+
for line in raw_rename.splitlines():
|
|
217
|
+
if line.startswith("R") and current_sym_path in line:
|
|
218
|
+
parts = line.split("\t")
|
|
219
|
+
if len(parts) >= 3 and parts[2] == current_sym_path:
|
|
220
|
+
old_p = parts[1]
|
|
221
|
+
events.append(
|
|
222
|
+
SymbolHistoryEvent(
|
|
223
|
+
commit_sha=c.sha,
|
|
224
|
+
date=c.date,
|
|
225
|
+
author=c.author,
|
|
226
|
+
message=c.message,
|
|
227
|
+
event_type="MOVED",
|
|
228
|
+
path=current_sym_path,
|
|
229
|
+
old_path=old_p,
|
|
230
|
+
confidence="FACT",
|
|
231
|
+
evidence=f"File moved from {old_p} to {current_sym_path}",
|
|
232
|
+
)
|
|
233
|
+
)
|
|
234
|
+
current_sym_path = old_p
|
|
235
|
+
found_move = True
|
|
236
|
+
break
|
|
237
|
+
|
|
238
|
+
if not found_move:
|
|
239
|
+
# Check if introduced
|
|
240
|
+
events.append(
|
|
241
|
+
SymbolHistoryEvent(
|
|
242
|
+
commit_sha=c.sha,
|
|
243
|
+
date=c.date,
|
|
244
|
+
author=c.author,
|
|
245
|
+
message=c.message,
|
|
246
|
+
event_type="INTRODUCED",
|
|
247
|
+
path=current_sym_path,
|
|
248
|
+
confidence="FACT",
|
|
249
|
+
evidence=f"Symbol created at {current_sym_path}:{curr_line}",
|
|
250
|
+
)
|
|
251
|
+
)
|
|
252
|
+
break
|
|
253
|
+
elif curr_hash is None and parent_hash is not None:
|
|
254
|
+
# Symbol was deleted or renamed in curr_content
|
|
255
|
+
events.append(
|
|
256
|
+
SymbolHistoryEvent(
|
|
257
|
+
commit_sha=c.sha,
|
|
258
|
+
date=c.date,
|
|
259
|
+
author=c.author,
|
|
260
|
+
message=c.message,
|
|
261
|
+
event_type="DELETED",
|
|
262
|
+
path=current_sym_path,
|
|
263
|
+
confidence="FACT",
|
|
264
|
+
evidence=f"Symbol removed in commit {c.sha[:8]}",
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
return SymbolHistoryReport(
|
|
269
|
+
symbol=symbol,
|
|
270
|
+
current_path=resolved_path,
|
|
271
|
+
events=events,
|
|
272
|
+
total_commits_evaluated=len(commits),
|
|
273
|
+
status="SUCCESS" if events else "NOT_FOUND",
|
|
274
|
+
detail=f"Traced {len(events)} history event(s) across {len(commits)} commits.",
|
|
275
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraph-engine
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.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,52 +35,104 @@ 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 MCP Engine (v2.
|
|
38
|
+
<h1 align="center">CodeGraph MCP Engine (v2.3.0)</h1>
|
|
39
39
|
|
|
40
40
|
<p align="center">
|
|
41
|
-
<strong>
|
|
41
|
+
<strong>Deterministic Codebase Intelligence for AI Coding Agents.</strong><br>
|
|
42
|
+
<em>High-performance Model Context Protocol (MCP) server for Claude Code, Cursor, Antigravity, Cline, and Codex.</em>
|
|
42
43
|
</p>
|
|
43
44
|
|
|
44
45
|
<p align="center">
|
|
45
|
-
<a href="https://pypi.org/project/codegraph-engine/2.
|
|
46
|
+
<a href="https://pypi.org/project/codegraph-engine/2.3.0/"><img src="https://img.shields.io/badge/pypi-codegraph--engine%20v2.3.0-blue.svg" alt="PyPI: codegraph-engine v2.3.0" /></a>
|
|
46
47
|
<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
|
-
<a href="src/codegraph/mcp/server.py"><img src="https://img.shields.io/badge/MCP-14%20default%20%7C%
|
|
48
|
-
<a href="tests/"><img src="https://img.shields.io/badge/pytest-
|
|
48
|
+
<a href="src/codegraph/mcp/server.py"><img src="https://img.shields.io/badge/MCP-14%20default%20%7C%2062%20full%20tools-2ea043.svg" alt="MCP Tools: 14 default | 62 full" /></a>
|
|
49
|
+
<a href="tests/"><img src="https://img.shields.io/badge/pytest-871%20passed-brightgreen.svg" alt="Tests: 871 passed" /></a>
|
|
49
50
|
<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(
|
|
51
|
+
<a href="src/codegraph/"><img src="https://img.shields.io/badge/mypy-0%20issues%20(87%20files)-blue.svg" alt="Mypy: strict" /></a>
|
|
52
|
+
<a href="https://raghurammrsd.github.io/CODE_GRAPH_MCP/"><img src="https://img.shields.io/badge/docs-GitHub%20Pages-0969da.svg" alt="Documentation: GitHub Pages" /></a>
|
|
51
53
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
52
54
|
</p>
|
|
53
55
|
|
|
54
56
|
<p align="center">
|
|
55
|
-
<a href="https://
|
|
56
|
-
<a href="
|
|
57
|
+
<a href="https://raghurammrsd.github.io/CODE_GRAPH_MCP/"><strong>Documentation Site</strong></a> •
|
|
58
|
+
<a href="https://pypi.org/project/codegraph-engine/2.3.0/"><strong>PyPI Package</strong></a> •
|
|
59
|
+
<a href="#overview"><strong>Overview</strong></a> •
|
|
60
|
+
<a href="#1-whats-new-in-v230-git-aware-intelligence"><strong>What's New in v2.3.0</strong></a> •
|
|
57
61
|
<a href="#2-quickstart-30-second-setup"><strong>Quickstart</strong></a> •
|
|
58
|
-
<a href="#4-real-world-cli-outputs"><strong>
|
|
62
|
+
<a href="#4-real-world-cli-outputs"><strong>CLI Outputs</strong></a> •
|
|
59
63
|
<a href="#6-database-intelligence"><strong>Database Intelligence</strong></a> •
|
|
60
64
|
<a href="#7-zero-friction-runtime-intelligence--static-reconciliation"><strong>Runtime Evidence</strong></a> •
|
|
61
|
-
<a href="#
|
|
62
|
-
<a href="
|
|
65
|
+
<a href="#8-git-aware-repository-intelligence"><strong>Git Intelligence</strong></a> •
|
|
66
|
+
<a href="#10-measured-performance-and-scaling-benchmarks"><strong>Benchmarks</strong></a> •
|
|
67
|
+
<a href="docs/agent-brain.md"><strong>62-Tool Reference</strong></a> •
|
|
63
68
|
<a href="https://github.com/raghurammrsd/CODE_GRAPH_MCP"><strong>GitHub</strong></a>
|
|
64
69
|
</p>
|
|
65
70
|
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Overview
|
|
74
|
+
|
|
75
|
+
### The Problem
|
|
76
|
+
|
|
77
|
+
When AI coding agents (such as Claude Code, Cursor, or Antigravity) explore complex enterprise repositories, text-based search (grep/ripgrep) forces them to parse large, multi-thousand-line files to reconstruct call chains, router mounts, dependency injection graphs, and ORM schemas. This consumes 60% to 80% of the LLM context window with irrelevant code and frequently leads to hallucinations regarding entity relationships and database structures.
|
|
78
|
+
|
|
79
|
+
### The Solution: CodeGraph MCP
|
|
80
|
+
|
|
81
|
+
**CodeGraph MCP provides deterministic, compiler-grade repository intelligence through the Model Context Protocol.** Instead of guessing based on lexical approximations, the AI agent queries a local, persistent SQLite index for verified AST relationships, framework router trees, database lineages, and live runtime observations—resolved in sub-5ms latency.
|
|
82
|
+
|
|
66
83
|
```text
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
84
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
85
|
+
│ AI CODING AGENT │
|
|
86
|
+
│ (Claude Code • Cursor • Antigravity) │
|
|
87
|
+
└──────────────────────────────┬──────────────────────────────┘
|
|
88
|
+
│ Model Context Protocol (stdio / SSE)
|
|
89
|
+
▼
|
|
90
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
91
|
+
│ CODEGRAPH MCP ENGINE │
|
|
92
|
+
├──────────────────────────────┬──────────────────────────────┤
|
|
93
|
+
│ AST Code Relationships │ Framework Route Hierarchy │
|
|
94
|
+
│ (Callers, Callees, DI) │ (FastAPI, Django, Express) │
|
|
95
|
+
├──────────────────────────────┼──────────────────────────────┤
|
|
96
|
+
│ Database Lineage & Schemas │ Non-Invasive Dev Tracing │
|
|
97
|
+
│ (SQLAlchemy, Prisma, ORM) │ (HTTP metrics, exceptions) │
|
|
98
|
+
└──────────────────────────────┴──────────────────────────────┘
|
|
99
|
+
│
|
|
100
|
+
▼
|
|
101
|
+
Deterministic • Local-First • Verified Evidence
|
|
70
102
|
```
|
|
71
103
|
|
|
72
|
-
|
|
73
|
-
|
|
104
|
+
### Core Architecture Capabilities
|
|
105
|
+
|
|
106
|
+
- **Zero Hallucination Guarantee**: Every returned entity and relationship is statically verified via Abstract Syntax Trees or explicitly flagged as `UNKNOWN` / `POSSIBLE`.
|
|
107
|
+
- **Sub-5ms Freshness Verification**: Monotonic commit tracking validates `git rev-parse HEAD` and porcelain status instantly, avoiding full-tree re-indexing on unchanged codebases.
|
|
108
|
+
- **Context Window Optimization**: Yields 65% to 85% token reduction by returning structured, bounded source slices rather than entire file dumps.
|
|
109
|
+
- **Zero-Friction Dev Interception (`codegraph run`)**: Wraps local development servers (e.g., `codegraph run npm run dev`, `codegraph run uvicorn main:app`) to capture real HTTP routes, latencies, and stack traces without application code changes.
|
|
110
|
+
- **Multi-Agent Setup (`codegraph install`)**: Automatically detects, configures, and verifies integrations for Claude Code, Cursor, Antigravity, and Cline.
|
|
74
111
|
|
|
75
|
-
|
|
112
|
+
> **Supported Languages & Frameworks:** Python (`FastAPI`, `Flask`, `Django`, `SQLAlchemy`, `Celery`, `pytest`) and TypeScript / JavaScript (`.ts`, `.tsx`, `.js`, `.jsx`, `Express.js`).
|
|
76
113
|
|
|
77
114
|

|
|
78
115
|
|
|
79
116
|
---
|
|
80
117
|
|
|
81
|
-
## 1. What's New in v2.
|
|
118
|
+
## 1. What's New in v2.3.0 (Git-Aware Intelligence)
|
|
82
119
|
|
|
83
|
-
Version `2.
|
|
120
|
+
Version `2.3.0` introduces compiler-grade **Git-Aware Repository Intelligence**, allowing AI agents and CI/CD pipelines to understand how code evolves across branches, commits, and working tree edits:
|
|
121
|
+
|
|
122
|
+
| Capability | CLI Command | MCP Tool | How It Solves Agent Failure Modes |
|
|
123
|
+
| :--- | :--- | :--- | :--- |
|
|
124
|
+
| **Working-Tree Freshness** | `codegraph git-state` | `get_git_state` | Tracks branch, HEAD vs indexed commit, modified/staged files with sub-millisecond status caching. Surfaces `CLEAN`, `DIRTY`, `STALE`, `REINDEXING`, `ERROR`. |
|
|
125
|
+
| **Structural AST Diff** | `codegraph git-diff [base] [head]` | `compare_git` | Semantic diff across Git revisions: identifies added/removed/modified functions, changed parameter signatures, and affected routes—not merely raw line diffs. |
|
|
126
|
+
| **Deep Impact & Visual Tree** | `codegraph git-impact --tree` | `get_change_impact` | Traverses downstream callers, callees, framework routes, DB writers, and affected test suites with token-bounded ranking and terminal ASCII tree visualization. |
|
|
127
|
+
| **Semantic Merge Conflicts** | `codegraph git-conflicts [base] [head]` | `detect_semantic_conflicts` | Detects silent contract breaks before merge: invoking functions or route handlers that were deleted or modified on the target branch. |
|
|
128
|
+
| **Context Freshness Gate** | `codegraph check-freshness [task]` | `check_context_freshness` | Determines whether previously compiled context remains `VALID`, `PARTIALLY_STALE`, or `STALE` without re-running full graph queries if unrelated files changed. |
|
|
129
|
+
| **Deterministic Symbol History** | `codegraph symbol-history <sym>` | `trace_symbol_history` | Reconstructs the exact commit lifecycle of any symbol (introduced, modified, moved, renamed, or deleted) with confidence labels. |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 1.1 What's New in v2.2.1
|
|
134
|
+
|
|
135
|
+
Version `2.2.1` introduced runtime telemetry reconciliation, SQLite WAL concurrency, and multi-transport SSE resilience:
|
|
84
136
|
|
|
85
137
|
| Bottleneck Solved | How It Worked Before | CodeGraph MCP v2.2.1 Solution | Impact |
|
|
86
138
|
| :--- | :--- | :--- | :--- |
|
|
@@ -404,6 +456,60 @@ UNRESOLVED_REFERENCE / POSSIBLE_CALLS (status = "UNKNOWN" | "POSSIBLE")
|
|
|
404
456
|
|
|
405
457
|
---
|
|
406
458
|
|
|
459
|
+
## 8. Git-Aware Repository Intelligence & Merge Conflict Safety
|
|
460
|
+
|
|
461
|
+
CodeGraph MCP v2.3.0 tracks the exact evolution of repository code across commits, branches, and working tree changes:
|
|
462
|
+
|
|
463
|
+
```text
|
|
464
|
+
Repository state
|
|
465
|
+
↓
|
|
466
|
+
Git change detection (CLEAN / DIRTY / STALE)
|
|
467
|
+
↓
|
|
468
|
+
Structural AST diff (functions, parameters, routes)
|
|
469
|
+
↓
|
|
470
|
+
Downstream impact analysis (callers, callees, tests, DB)
|
|
471
|
+
↓
|
|
472
|
+
Context freshness validation (VALID / PARTIALLY_STALE / STALE)
|
|
473
|
+
↓
|
|
474
|
+
Evidence-backed answer
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### 1. Working Tree & Index Freshness (`codegraph git-state`)
|
|
478
|
+
Tracks current branch, current HEAD commit, indexed commit, and modified/staged files with sub-millisecond status caching:
|
|
479
|
+
```bash
|
|
480
|
+
codegraph git-state
|
|
481
|
+
```
|
|
482
|
+
Never silently serves stale repository facts. Explicitly reports `CLEAN`, `DIRTY`, `STALE`, `REINDEXING`, or `ERROR`.
|
|
483
|
+
|
|
484
|
+
### 2. Deep Visual Downstream Impact Tree (`codegraph git-impact --tree`)
|
|
485
|
+
Traverses affected callers, routes, tests, and DB writers with token-bounded results and visual ASCII hierarchy:
|
|
486
|
+
```bash
|
|
487
|
+
codegraph git-impact --tree
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### 3. Semantic & Contract Merge Conflicts (`codegraph git-conflicts`)
|
|
491
|
+
Detects silent merge conflicts before git merge or pull request landing—such as branch A invoking a function or route handler that branch B deleted or altered:
|
|
492
|
+
```bash
|
|
493
|
+
codegraph git-conflicts main HEAD
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 4. Structural AST Diff (`codegraph git-diff`)
|
|
497
|
+
Computes semantic AST differences between Git revisions (added/removed/modified symbols, changed parameter signatures):
|
|
498
|
+
```bash
|
|
499
|
+
codegraph git-diff HEAD~1 HEAD
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 5. Deterministic Symbol History (`codegraph symbol-history`)
|
|
503
|
+
Traces symbol lifecycle across commits (introduced, modified, moved, renamed, or deleted):
|
|
504
|
+
```bash
|
|
505
|
+
codegraph symbol-history resolve_target
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 6. GitHub Action for Pull Request Impact
|
|
509
|
+
Automate change impact directly in your CI pipeline with `.github/workflows/codegraph-pr-impact.yml` and `.github/actions/codegraph-impact/action.yml`.
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
407
513
|
## 9. Measured Performance and Scaling Benchmarks
|
|
408
514
|
|
|
409
515
|
### 4-Tier Scaling Summary (`54` → `2,504` Files)
|
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
codegraph/__init__.py,sha256=
|
|
1
|
+
codegraph/__init__.py,sha256=EmyDwINWrwVqpTtH6eNgda5rgun2zkN-4M2G52Uobk4,845
|
|
2
2
|
codegraph/agent.py,sha256=We0TWEXSMBBz6t2NQEGPB6gv-2P1IwyCmxoFGPN_CBA,911
|
|
3
3
|
codegraph/agent_brain.py,sha256=xy0TWQsu4_xmuRlzrN-xbcLCBKcyTbwUAyW6PDW3FvI,130406
|
|
4
|
-
codegraph/agent_capabilities.py,sha256=
|
|
4
|
+
codegraph/agent_capabilities.py,sha256=88bZA1PpCEZ2Q-JwSxX-JuOEH-I9Dd1iTBTEOND8yXE,194853
|
|
5
5
|
codegraph/agent_rules.py,sha256=wxy8N4-6jfCEeb_QSKF7AMOPF_kRW8rZsrYHQZO6N3w,37171
|
|
6
6
|
codegraph/architecture.py,sha256=8QAiAihwCJ_-jIBTUS4eEY1uk_TwpYh09hWRQc8sBjc,14023
|
|
7
7
|
codegraph/audit.py,sha256=j6fFL6b4vKfnAdUYU7goqQBv4ysrxy-ecBJvT8rYoSI,3301
|
|
8
8
|
codegraph/binding_resolver.py,sha256=GgpXoUB2ue5vVF5LBoMAlXYk2ru1AHUhIynbq-y1afI,26569
|
|
9
|
+
codegraph/branch_comparison.py,sha256=8sh6iTXDdGDPjJ2NN2Xtrsl66gCh1tvt7FSy4ioCaaE,6626
|
|
9
10
|
codegraph/cache.py,sha256=42Fyl51EsMwcYDv5loosIicVvvrFnIw7JrqKJ7owZtw,2992
|
|
10
|
-
codegraph/
|
|
11
|
+
codegraph/change_impact.py,sha256=430-rtrgPVFZDZD6wPNbtom2rxlnRRp8TmUlHvJK4NI,13578
|
|
12
|
+
codegraph/cli.py,sha256=0xR2Nsr7X4CJ9IYaObusM45h6atpdb9nkax4tX8KpN0,68362
|
|
11
13
|
codegraph/cli_output.py,sha256=HK83BQ9iAqQjE0LPUrMBube4N7sXU5T4Y-y3Otq0Hyw,5677
|
|
12
14
|
codegraph/config.py,sha256=8-LFxMfg84H77dcDhmsbJrLaB3g5lY_OiP77Qji2GK4,1975
|
|
13
15
|
codegraph/constraints.py,sha256=AR_d07ENmbcDhWmcbruy4DvBYXsEdvSwkatyQ6JO-dE,8554
|
|
14
16
|
codegraph/context.py,sha256=lXHZ0iPKuHVmmvMCBmZnqhoAf1L8hktAAFyUtuon9CQ,95413
|
|
17
|
+
codegraph/context_freshness.py,sha256=UuYBNua8VteX6yGEtRAvDlvEdSMuuzxwLpMuJEb8YJs,14241
|
|
15
18
|
codegraph/epistemic.py,sha256=xyGzFAHx8gtArVSrPLwSAN2PV20uUi1nUWtmgEKMS7Y,6051
|
|
16
19
|
codegraph/errors.py,sha256=QZk92Fr95qx-rfU3W5FVOEy1KjnKgtlbMykTnj4Rhos,10299
|
|
17
20
|
codegraph/evidence_contract.py,sha256=EYOcYeiCrdcmb7tQF8WkFUyz06iSTcUs5F-ssA4RFOA,22802
|
|
18
21
|
codegraph/frameworks.py,sha256=c5KIE8BlWvU4vAkKnuTZVtxwIOFxcYOlTQHEwnbIH-w,30143
|
|
19
22
|
codegraph/freshness.py,sha256=GIlva-vaugLBRUjvi6Eo9fQ36O5Lykgl6YBH0eqCudQ,12090
|
|
20
23
|
codegraph/git.py,sha256=q86cpC_HyEccnK2kuZcWMp-39gjSECs0D4Qbvq27P2A,12069
|
|
24
|
+
codegraph/git_state.py,sha256=gCTmaR0VF1yWz_zxk_jwrR-v5LaQzcltwc2vgyv-_R0,20305
|
|
21
25
|
codegraph/installer.py,sha256=JwjOHWZv2oMYEjQ6vYIaAn_v94P-e-Ra0QcQWlLhhmo,66403
|
|
22
26
|
codegraph/interrogation.py,sha256=1_lSamzTo-KVtIfq6qH7jr4UiEgJAdpO__Bvsz95K8U,81687
|
|
23
27
|
codegraph/mcp_diagnostics.py,sha256=Am2Ad7OwBUPDxklHNk6XPTgBaba-_bi5q2mWYI-pVaE,33430
|
|
@@ -33,7 +37,10 @@ codegraph/ranking.py,sha256=Zku5csLQ0_-9RmsYcdQUzTr5sDrHzNHRFQXtrFwleAc,16975
|
|
|
33
37
|
codegraph/resolver.py,sha256=CLYEarvBl5k8SWerRAgSQ1xx2mq-bNFm9W9qbvh6Jbg,127846
|
|
34
38
|
codegraph/retrieval_policy.py,sha256=GwaiDfOZYDX_o6lvA0YhNL51iGkx0VIvKx_CEbD90d0,11318
|
|
35
39
|
codegraph/route_composer.py,sha256=mPXQL4jivfp0QmltFFHMx-8eNkke5nq-U8tE6tH5wbY,15153
|
|
40
|
+
codegraph/semantic_conflicts.py,sha256=1Qa0XoJS41i5x4UGKobb5IN9sEwtjszgZP6-xppYP7o,11388
|
|
36
41
|
codegraph/semantic_decorators.py,sha256=dK0FlGFxV0yQnqAJvtZoPANdWYLx8swunufgGfMimH4,14900
|
|
42
|
+
codegraph/structural_diff.py,sha256=BAlpCnXJe5DS5yLw2ODVcQoTtsDXE0xbrnMzOrwcSp8,20231
|
|
43
|
+
codegraph/symbol_history.py,sha256=9PgINDtEWAG3kg5oPkrGkkfs_GtbD3ciUg_35hng5G0,10628
|
|
37
44
|
codegraph/target_resolver.py,sha256=aE-R0oyCHI2uy35gOE_5I4mFOBoiajsypeK65l4TWj0,12965
|
|
38
45
|
codegraph/task.py,sha256=dbku1uEfcBrrkY8bFCjoFMwRnTxa7oLxAfnTGzY5dTw,24740
|
|
39
46
|
codegraph/tool_selection_eval.py,sha256=2TWkhHqQ9KKEohM_gcX0k5LqymU9K2VZTPCuYbhZI10,48833
|
|
@@ -58,7 +65,7 @@ codegraph/llm/__init__.py,sha256=rro4OuSOUFKhBq0-Rg-VAU7dvc6LS88YgdE8GfClb4E,89
|
|
|
58
65
|
codegraph/llm/base.py,sha256=M5f4mawPchXqlb7U7DF0cnGlDEy66KbuhhZc1hExZdU,406
|
|
59
66
|
codegraph/llm/context.py,sha256=TT5WIe3gTrvbQCASf2XDfyhwG3Cr5QPgqw9neXDM8qQ,641
|
|
60
67
|
codegraph/mcp/__init__.py,sha256=BmjrnksGkbG7TPqwbyQvgYj9uei8pFSFpfkRpaGVdJU,63
|
|
61
|
-
codegraph/mcp/server.py,sha256=
|
|
68
|
+
codegraph/mcp/server.py,sha256=t2mXSezXtTFy6al8TDZPDMSTvAoWyEyQ4YUcuDOKgDo,67822
|
|
62
69
|
codegraph/memory/__init__.py,sha256=yfQgSZ9Tii6PPZiLW0ImwC2k-Bg6m7mnUm_K1laBems,58
|
|
63
70
|
codegraph/memory/store.py,sha256=K3iD9VWF5if4OmYCTb5KxtZ3zj45kfEKmz8yivWzP-M,1490
|
|
64
71
|
codegraph/resources/__init__.py,sha256=KPpsePEf6cNVvpMI4tnIbYVSw6Q77kaOP6wcmEko7tE,1296
|
|
@@ -79,9 +86,9 @@ codegraph/search/semantic.py,sha256=QZaJVEoOZIZrp4O6SmUAzMiqMPfopgmPSpqzL3T7GVg,
|
|
|
79
86
|
codegraph/security/__init__.py,sha256=L1j4pRC4XTBgYk6e243MmpXskq5mHDwOpd9JHV_-0j8,1249
|
|
80
87
|
codegraph/security/paths.py,sha256=BPWbADXyuVCtCiqeZb8YSe4hYFTr-R-Gj1sYP4Jpy8M,5451
|
|
81
88
|
codegraph/security/redaction.py,sha256=CfkBYrFswybGw-g8IeKbW-qkZ5OXaHoSVynLGmGIh2Y,23371
|
|
82
|
-
codegraph_engine-2.
|
|
83
|
-
codegraph_engine-2.
|
|
84
|
-
codegraph_engine-2.
|
|
85
|
-
codegraph_engine-2.
|
|
86
|
-
codegraph_engine-2.
|
|
87
|
-
codegraph_engine-2.
|
|
89
|
+
codegraph_engine-2.3.0.dist-info/licenses/LICENSE,sha256=kMXNS9xyan1jJAG5_jORb8RyVeY-_Httz3JAtCjjyxI,1093
|
|
90
|
+
codegraph_engine-2.3.0.dist-info/METADATA,sha256=JOYl8i7Wtm9zpBnOC5yo1Y-BCkwK_ks_80pRKSH1jDY,44880
|
|
91
|
+
codegraph_engine-2.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
92
|
+
codegraph_engine-2.3.0.dist-info/entry_points.txt,sha256=U2xQ3yhqOaaDyFtV9p7N0FDref1VEk56RE_Bnvrnycc,48
|
|
93
|
+
codegraph_engine-2.3.0.dist-info/top_level.txt,sha256=RqBj9sPbifZTb9aeHtnbxTgKJvfHIQdmYE1Brv8Wdkg,10
|
|
94
|
+
codegraph_engine-2.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|