code-review-graph 2.2.0__tar.gz → 2.2.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.
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/.gitignore +20 -15
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/PKG-INFO +1 -1
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/cli.py +0 -2
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/graph.py +2 -3
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/parser.py +45 -7
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/prompts.py +3 -1
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/skills.py +9 -9
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/context.py +4 -4
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/FEATURES.md +16 -1
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/LLM-OPTIMIZED-REFERENCE.md +11 -10
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/pyproject.toml +1 -1
- code_review_graph-2.2.0/.claude-plugin/marketplace.json +0 -21
- code_review_graph-2.2.0/.claude-plugin/plugin.json +0 -21
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/LICENSE +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/README.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code-review-graph-vscode/LICENSE +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code-review-graph-vscode/README.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/__init__.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/__main__.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/changes.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/communities.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/constants.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/embeddings.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/__init__.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/__init__.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/build_performance.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/flow_completeness.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/impact_accuracy.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/search_quality.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/token_efficiency.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/express.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/fastapi.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/flask.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/gin.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/httpx.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/nextjs.yaml +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/reporter.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/runner.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/scorer.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/token_benchmark.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/flows.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/hints.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/incremental.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/main.py +2 -2
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/migrations.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/refactor.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/registry.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/search.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/__init__.py +3 -3
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/_common.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/build.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/community_tools.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/docs.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/flows_tools.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/query.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/refactor_tools.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/registry_tools.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/review.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tsconfig_resolver.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/visualization.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/wiki.py +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/COMMANDS.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/INDEX.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/LEGAL.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/ROADMAP.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/TROUBLESHOOTING.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/USAGE.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/architecture.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/schema.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/hooks/hooks.json +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/hooks/session-start.sh +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/build-graph/SKILL.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/review-delta/SKILL.md +0 -0
- {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/review-pr/SKILL.md +0 -0
|
@@ -32,11 +32,16 @@ env/
|
|
|
32
32
|
.DS_Store
|
|
33
33
|
Thumbs.db
|
|
34
34
|
|
|
35
|
-
# Node
|
|
35
|
+
# Node
|
|
36
36
|
node_modules/
|
|
37
37
|
|
|
38
|
+
# VS Code extension build artifacts
|
|
39
|
+
code-review-graph-vscode/dist/
|
|
40
|
+
*.vsix
|
|
41
|
+
|
|
38
42
|
# Claude Code
|
|
39
43
|
.claude/
|
|
44
|
+
.claude-plugin/
|
|
40
45
|
|
|
41
46
|
# Coverage
|
|
42
47
|
htmlcov/
|
|
@@ -49,26 +54,24 @@ htmlcov/
|
|
|
49
54
|
# mypy
|
|
50
55
|
.mypy_cache/
|
|
51
56
|
|
|
52
|
-
#
|
|
53
|
-
medium/
|
|
54
|
-
|
|
55
|
-
# Superpowers brainstorm
|
|
56
|
-
.superpowers/
|
|
57
|
-
docs/superpowers/plans/
|
|
58
|
-
docs/superpowers/specs/
|
|
59
|
-
|
|
60
|
-
# Diagrams (PNGs + script tracked, excalidraw sources gitignored)
|
|
61
|
-
diagrams/*.excalidraw
|
|
62
|
-
diagrams/export_pngs.mjs
|
|
57
|
+
# Excalidraw source files (PNGs are tracked, sources are not)
|
|
63
58
|
*.excalidraw
|
|
59
|
+
diagrams/export_pngs.mjs
|
|
64
60
|
|
|
65
|
-
# Evaluation test repos
|
|
61
|
+
# Evaluation (generated output — test repos, results, reports)
|
|
66
62
|
evaluate/test_repos/
|
|
63
|
+
evaluate/results/
|
|
64
|
+
evaluate/reports/
|
|
67
65
|
|
|
68
|
-
#
|
|
66
|
+
# Superpowers brainstorm docs
|
|
67
|
+
.superpowers/
|
|
68
|
+
docs/superpowers/
|
|
69
|
+
|
|
70
|
+
# Draft/duplicate assets
|
|
69
71
|
docs/assets/marketing-diagram*
|
|
70
72
|
|
|
71
|
-
# One-off
|
|
73
|
+
# One-off docs (audits, analyses, plans, articles)
|
|
74
|
+
medium/
|
|
72
75
|
Quality-Audit-Report.docx
|
|
73
76
|
accessibility-audit.md
|
|
74
77
|
cross-audit-synthesis.md
|
|
@@ -76,3 +79,5 @@ design-critique.md
|
|
|
76
79
|
design-handoff.md
|
|
77
80
|
design-system-audit.md
|
|
78
81
|
research-synthesis.md
|
|
82
|
+
code-review-graph-analysis.md
|
|
83
|
+
SCALING_AND_TOKEN_EFFICIENCY_PLAN.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-review-graph
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code
|
|
5
5
|
Project-URL: Homepage, https://code-review-graph.com
|
|
6
6
|
Project-URL: Repository, https://github.com/tirth8205/code-review-graph
|
|
@@ -8,6 +8,7 @@ Supports impact-radius queries and subgraph extraction.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
|
+
import logging
|
|
11
12
|
import sqlite3
|
|
12
13
|
import threading
|
|
13
14
|
import time
|
|
@@ -15,15 +16,13 @@ from dataclasses import dataclass
|
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
from typing import Any, Optional
|
|
17
18
|
|
|
18
|
-
import logging
|
|
19
|
-
|
|
20
19
|
import networkx as nx
|
|
21
20
|
|
|
22
21
|
from .constants import BFS_ENGINE, MAX_IMPACT_DEPTH, MAX_IMPACT_NODES
|
|
23
22
|
from .migrations import get_schema_version, run_migrations
|
|
23
|
+
from .parser import EdgeInfo, NodeInfo
|
|
24
24
|
|
|
25
25
|
logger = logging.getLogger(__name__)
|
|
26
|
-
from .parser import EdgeInfo, NodeInfo
|
|
27
26
|
|
|
28
27
|
# ---------------------------------------------------------------------------
|
|
29
28
|
# Schema
|
|
@@ -242,6 +242,8 @@ _TEST_FILE_PATTERNS = [
|
|
|
242
242
|
re.compile(r".*_test\.dart$"),
|
|
243
243
|
re.compile(r"test[_-].*\.[rR]$"),
|
|
244
244
|
re.compile(r"tests/testthat/"),
|
|
245
|
+
re.compile(r".*Test\.kt$"),
|
|
246
|
+
re.compile(r".*Test\.java$"),
|
|
245
247
|
]
|
|
246
248
|
|
|
247
249
|
_TEST_RUNNER_NAMES = frozenset({
|
|
@@ -249,20 +251,29 @@ _TEST_RUNNER_NAMES = frozenset({
|
|
|
249
251
|
"beforeAll", "afterAll",
|
|
250
252
|
})
|
|
251
253
|
|
|
254
|
+
# Annotations/decorators that mark test methods (JUnit, TestNG, etc.)
|
|
255
|
+
_TEST_ANNOTATIONS = frozenset({
|
|
256
|
+
"Test", "ParameterizedTest", "RepeatedTest", "TestFactory",
|
|
257
|
+
"org.junit.Test", "org.junit.jupiter.api.Test",
|
|
258
|
+
})
|
|
259
|
+
|
|
252
260
|
|
|
253
261
|
def _is_test_file(path: str) -> bool:
|
|
254
262
|
return any(p.search(path) for p in _TEST_FILE_PATTERNS)
|
|
255
263
|
|
|
256
264
|
|
|
257
|
-
def _is_test_function(
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
def _is_test_function(
|
|
266
|
+
name: str, file_path: str, decorators: tuple[str, ...] = (),
|
|
267
|
+
) -> bool:
|
|
268
|
+
"""A function is a test if its name matches test patterns, it lives
|
|
269
|
+
in a test file and has a test-runner name, or it has a @Test annotation.
|
|
260
270
|
"""
|
|
261
271
|
if any(p.search(name) for p in _TEST_PATTERNS):
|
|
262
272
|
return True
|
|
263
|
-
# In test files, treat common JS/TS test-runner wrappers as tests
|
|
264
273
|
if _is_test_file(file_path) and name in _TEST_RUNNER_NAMES:
|
|
265
274
|
return True
|
|
275
|
+
if decorators and any(d in _TEST_ANNOTATIONS for d in decorators):
|
|
276
|
+
return True
|
|
266
277
|
return False
|
|
267
278
|
|
|
268
279
|
|
|
@@ -1540,7 +1551,26 @@ class CodeParser:
|
|
|
1540
1551
|
if not name:
|
|
1541
1552
|
return False
|
|
1542
1553
|
|
|
1543
|
-
|
|
1554
|
+
# Extract annotations/decorators for test detection
|
|
1555
|
+
decorators: tuple[str, ...] = ()
|
|
1556
|
+
deco_list: list[str] = []
|
|
1557
|
+
for sub in child.children:
|
|
1558
|
+
# Java/Kotlin/C#: annotations inside a modifiers child
|
|
1559
|
+
if sub.type == "modifiers":
|
|
1560
|
+
for mod in sub.children:
|
|
1561
|
+
if mod.type in ("annotation", "marker_annotation"):
|
|
1562
|
+
text = mod.text.decode("utf-8", errors="replace")
|
|
1563
|
+
deco_list.append(text.lstrip("@").strip())
|
|
1564
|
+
# Python: check parent decorated_definition for decorator siblings
|
|
1565
|
+
if child.parent and child.parent.type == "decorated_definition":
|
|
1566
|
+
for sib in child.parent.children:
|
|
1567
|
+
if sib.type == "decorator":
|
|
1568
|
+
text = sib.text.decode("utf-8", errors="replace")
|
|
1569
|
+
deco_list.append(text.lstrip("@").strip())
|
|
1570
|
+
if deco_list:
|
|
1571
|
+
decorators = tuple(deco_list)
|
|
1572
|
+
|
|
1573
|
+
is_test = _is_test_function(name, file_path, decorators)
|
|
1544
1574
|
kind = "Test" if is_test else "Function"
|
|
1545
1575
|
qualified = self._qualify(name, file_path, enclosing_class)
|
|
1546
1576
|
params = self._get_params(child, language, source)
|
|
@@ -2432,7 +2462,8 @@ class CodeParser:
|
|
|
2432
2462
|
return None # method child not found
|
|
2433
2463
|
|
|
2434
2464
|
# Simple call: func_name(args)
|
|
2435
|
-
|
|
2465
|
+
# Kotlin uses "simple_identifier" instead of "identifier".
|
|
2466
|
+
if first.type in ("identifier", "simple_identifier"):
|
|
2436
2467
|
return first.text.decode("utf-8", errors="replace")
|
|
2437
2468
|
|
|
2438
2469
|
# Perl: function_call_expression / ambiguous_function_call_expression
|
|
@@ -2450,18 +2481,25 @@ class CodeParser:
|
|
|
2450
2481
|
return None
|
|
2451
2482
|
|
|
2452
2483
|
# Method call: obj.method(args)
|
|
2484
|
+
# Kotlin uses "navigation_expression" for member access (obj.method).
|
|
2453
2485
|
member_types = (
|
|
2454
2486
|
"attribute", "member_expression",
|
|
2455
2487
|
"field_expression", "selector_expression",
|
|
2488
|
+
"navigation_expression",
|
|
2456
2489
|
)
|
|
2457
2490
|
if first.type in member_types:
|
|
2458
2491
|
# Get the rightmost identifier (the method name)
|
|
2492
|
+
# Kotlin navigation_expression uses navigation_suffix > simple_identifier.
|
|
2459
2493
|
for child in reversed(first.children):
|
|
2460
2494
|
if child.type in (
|
|
2461
2495
|
"identifier", "property_identifier", "field_identifier",
|
|
2462
|
-
"field_name",
|
|
2496
|
+
"field_name", "simple_identifier",
|
|
2463
2497
|
):
|
|
2464
2498
|
return child.text.decode("utf-8", errors="replace")
|
|
2499
|
+
if child.type == "navigation_suffix":
|
|
2500
|
+
for sub in child.children:
|
|
2501
|
+
if sub.type == "simple_identifier":
|
|
2502
|
+
return sub.text.decode("utf-8", errors="replace")
|
|
2465
2503
|
return first.text.decode("utf-8", errors="replace")
|
|
2466
2504
|
|
|
2467
2505
|
# Scoped call (e.g., Rust path::func())
|
|
@@ -12,7 +12,8 @@ detail_level="minimal" first patterns with get_minimal_context entry point.
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
_TOKEN_EFFICIENCY_PREAMBLE =
|
|
15
|
+
_TOKEN_EFFICIENCY_PREAMBLE = ( # nosec B105 — prompt template, not a password
|
|
16
|
+
"""\
|
|
16
17
|
## Rules for Token-Efficient Graph Usage
|
|
17
18
|
1. ALWAYS call `get_minimal_context` first with a task description.
|
|
18
19
|
2. Use `detail_level="minimal"` on all tool calls unless the minimal output \
|
|
@@ -25,6 +26,7 @@ scans (list_communities with full members).
|
|
|
25
26
|
6. When reviewing changes: detect_changes(detail_level="minimal") → only \
|
|
26
27
|
expand on high-risk items.
|
|
27
28
|
"""
|
|
29
|
+
)
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def review_changes_prompt(base: str = "HEAD~1") -> list[dict]:
|
|
@@ -141,7 +141,7 @@ def install_platform_configs(
|
|
|
141
141
|
existing: dict[str, Any] = {}
|
|
142
142
|
if config_path.exists():
|
|
143
143
|
try:
|
|
144
|
-
existing = json.loads(config_path.read_text())
|
|
144
|
+
existing = json.loads(config_path.read_text(encoding="utf-8"))
|
|
145
145
|
except (json.JSONDecodeError, OSError):
|
|
146
146
|
logger.warning("Invalid JSON in %s, will overwrite.", config_path)
|
|
147
147
|
existing = {}
|
|
@@ -176,7 +176,7 @@ def install_platform_configs(
|
|
|
176
176
|
print(f" [dry-run] {plat['name']}: would write {config_path}")
|
|
177
177
|
else:
|
|
178
178
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
179
|
-
config_path.write_text(json.dumps(existing, indent=2) + "\n")
|
|
179
|
+
config_path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
|
|
180
180
|
print(f" {plat['name']}: configured {config_path}")
|
|
181
181
|
|
|
182
182
|
configured.append(plat["name"])
|
|
@@ -325,7 +325,7 @@ def generate_skills(repo_root: Path, skills_dir: Path | None = None) -> Path:
|
|
|
325
325
|
"---\n\n"
|
|
326
326
|
f"{skill['body']}\n"
|
|
327
327
|
)
|
|
328
|
-
path.write_text(content)
|
|
328
|
+
path.write_text(content, encoding="utf-8")
|
|
329
329
|
logger.info("Wrote skill: %s", path)
|
|
330
330
|
|
|
331
331
|
return skills_dir
|
|
@@ -345,13 +345,13 @@ def generate_hooks_config() -> dict[str, Any]:
|
|
|
345
345
|
"PostToolUse": [
|
|
346
346
|
{
|
|
347
347
|
"matcher": "Edit|Write|Bash",
|
|
348
|
-
"command": "code-review-graph update --
|
|
348
|
+
"command": "code-review-graph update --skip-flows",
|
|
349
349
|
"timeout": 5000,
|
|
350
350
|
},
|
|
351
351
|
],
|
|
352
352
|
"SessionStart": [
|
|
353
353
|
{
|
|
354
|
-
"command": "code-review-graph status
|
|
354
|
+
"command": "code-review-graph status",
|
|
355
355
|
"timeout": 3000,
|
|
356
356
|
},
|
|
357
357
|
],
|
|
@@ -381,14 +381,14 @@ def install_hooks(repo_root: Path) -> None:
|
|
|
381
381
|
existing: dict[str, Any] = {}
|
|
382
382
|
if settings_path.exists():
|
|
383
383
|
try:
|
|
384
|
-
existing = json.loads(settings_path.read_text())
|
|
384
|
+
existing = json.loads(settings_path.read_text(encoding="utf-8"))
|
|
385
385
|
except (json.JSONDecodeError, OSError) as exc:
|
|
386
386
|
logger.warning("Could not read existing %s: %s", settings_path, exc)
|
|
387
387
|
|
|
388
388
|
hooks_config = generate_hooks_config()
|
|
389
389
|
existing.update(hooks_config)
|
|
390
390
|
|
|
391
|
-
settings_path.write_text(json.dumps(existing, indent=2) + "\n")
|
|
391
|
+
settings_path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
|
|
392
392
|
logger.info("Wrote hooks config: %s", settings_path)
|
|
393
393
|
|
|
394
394
|
|
|
@@ -445,7 +445,7 @@ def _inject_instructions(file_path: Path, marker: str, section: str) -> bool:
|
|
|
445
445
|
"""
|
|
446
446
|
existing = ""
|
|
447
447
|
if file_path.exists():
|
|
448
|
-
existing = file_path.read_text()
|
|
448
|
+
existing = file_path.read_text(encoding="utf-8")
|
|
449
449
|
|
|
450
450
|
if marker in existing:
|
|
451
451
|
logger.info("%s already contains instructions, skipping.", file_path.name)
|
|
@@ -453,7 +453,7 @@ def _inject_instructions(file_path: Path, marker: str, section: str) -> bool:
|
|
|
453
453
|
|
|
454
454
|
separator = "\n" if existing and not existing.endswith("\n") else ""
|
|
455
455
|
extra_newline = "\n" if existing else ""
|
|
456
|
-
file_path.write_text(existing + separator + extra_newline + section)
|
|
456
|
+
file_path.write_text(existing + separator + extra_newline + section, encoding="utf-8")
|
|
457
457
|
logger.info("Appended MCP tools section to %s", file_path)
|
|
458
458
|
return True
|
|
459
459
|
|
|
@@ -91,21 +91,21 @@ def get_minimal_context(
|
|
|
91
91
|
# 3. Top 3 communities
|
|
92
92
|
communities: list[str] = []
|
|
93
93
|
try:
|
|
94
|
-
rows = store.
|
|
94
|
+
rows = store._conn.execute(
|
|
95
95
|
"SELECT name FROM communities ORDER BY size DESC LIMIT 3"
|
|
96
96
|
).fetchall()
|
|
97
97
|
communities = [r[0] for r in rows]
|
|
98
|
-
except Exception:
|
|
98
|
+
except Exception: # nosec B110 — table may not exist yet
|
|
99
99
|
pass
|
|
100
100
|
|
|
101
101
|
# 4. Top 3 critical flows
|
|
102
102
|
flows: list[str] = []
|
|
103
103
|
try:
|
|
104
|
-
rows = store.
|
|
104
|
+
rows = store._conn.execute(
|
|
105
105
|
"SELECT name FROM flows ORDER BY criticality DESC LIMIT 3"
|
|
106
106
|
).fetchall()
|
|
107
107
|
flows = [r[0] for r in rows]
|
|
108
|
-
except Exception:
|
|
108
|
+
except Exception: # nosec B110 — table may not exist yet
|
|
109
109
|
pass
|
|
110
110
|
|
|
111
111
|
# 5. Suggest next tools based on task keywords
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
# Features
|
|
2
2
|
|
|
3
|
-
## v2.1
|
|
3
|
+
## v2.2.1 (Current)
|
|
4
|
+
- **24 MCP tools** (up from 22): Added `get_minimal_context` and `run_postprocess`.
|
|
5
|
+
- **Parallel parsing**: `ProcessPoolExecutor` for 3-5x faster builds on large repos.
|
|
6
|
+
- **Lazy post-processing**: `postprocess="full"|"minimal"|"none"` to skip expensive steps.
|
|
7
|
+
- **SQLite-native BFS**: Recursive CTE replaces NetworkX for impact analysis (faster on large graphs).
|
|
8
|
+
- **Token-efficient output**: `detail_level="minimal"` on 8 tools for 40-60% token reduction.
|
|
9
|
+
- **`get_minimal_context`**: Ultra-compact entry point (~100 tokens) with task-based tool routing.
|
|
10
|
+
- **Incremental flow/community updates**: Only re-trace affected flows, skip community re-detection when unaffected.
|
|
11
|
+
- **Visualization aggregation**: Community/file/auto modes with drill-down for 5k+ node graphs.
|
|
12
|
+
- **Token-efficiency benchmarks**: 5 workflow benchmarks in eval framework.
|
|
13
|
+
- **Pre-computed summary tables**: DB schema v6 with `community_summaries`, `flow_snapshots`, `risk_index`.
|
|
14
|
+
- **Configurable limits**: `CRG_MAX_IMPACT_NODES`, `CRG_MAX_IMPACT_DEPTH`, `CRG_DEPENDENT_HOPS`, etc.
|
|
15
|
+
- **Multi-hop dependents**: N-hop dependent discovery (default 2) with 500-file cap.
|
|
16
|
+
- **615 tests** across 22 test files.
|
|
17
|
+
|
|
18
|
+
## v2.1.0
|
|
4
19
|
- **22 MCP tools** (up from 9): 13 new tools for flows, communities, architecture, refactoring, wiki, multi-repo, and risk-scored change detection.
|
|
5
20
|
- **5 MCP prompts**: `review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` workflow templates.
|
|
6
21
|
- **18 languages** (up from 15): Added Dart, R, Perl support.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# LLM-OPTIMIZED REFERENCE -- code-review-graph v2.1
|
|
1
|
+
# LLM-OPTIMIZED REFERENCE -- code-review-graph v2.2.1
|
|
2
2
|
|
|
3
3
|
Claude Code: Read ONLY the exact `<section>` you need. Never load the whole file.
|
|
4
4
|
|
|
@@ -7,15 +7,15 @@ Quick install: pip install code-review-graph
|
|
|
7
7
|
Then: code-review-graph install && code-review-graph build
|
|
8
8
|
First run: /code-review-graph:build-graph
|
|
9
9
|
After that use only delta/pr commands.
|
|
10
|
-
|
|
10
|
+
ALWAYS start with get_minimal_context_tool(task="your task") — returns ~100 tokens with risk, communities, flows, and suggested next tools.
|
|
11
|
+
Use detail_level="minimal" on all subsequent calls unless you need more detail.
|
|
11
12
|
</section>
|
|
12
13
|
|
|
13
14
|
<section name="review-delta">
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Target: <800 tokens total context.
|
|
15
|
+
1. Call get_minimal_context_tool(task="review changes") first.
|
|
16
|
+
2. If risk is low: detect_changes_tool(detail_level="minimal") → report summary.
|
|
17
|
+
3. If risk is medium/high: detect_changes_tool(detail_level="standard") → expand on high-risk items.
|
|
18
|
+
Target: ≤5 tool calls, ≤800 tokens total context.
|
|
19
19
|
</section>
|
|
20
20
|
|
|
21
21
|
<section name="review-pr">
|
|
@@ -24,10 +24,11 @@ Never include full files unless explicitly asked.
|
|
|
24
24
|
</section>
|
|
25
25
|
|
|
26
26
|
<section name="commands">
|
|
27
|
-
MCP tools (
|
|
27
|
+
MCP tools (24): get_minimal_context_tool, build_or_update_graph_tool, run_postprocess_tool, get_impact_radius_tool, query_graph_tool, get_review_context_tool, semantic_search_nodes_tool, embed_graph_tool, list_graph_stats_tool, get_docs_section_tool, find_large_functions_tool, list_flows_tool, get_flow_tool, get_affected_flows_tool, list_communities_tool, get_community_tool, get_architecture_overview_tool, detect_changes_tool, refactor_tool, apply_refactor_tool, generate_wiki_tool, get_wiki_page_tool, list_repos_tool, cross_repo_search_tool
|
|
28
28
|
MCP prompts (5): review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check
|
|
29
29
|
Skills: build-graph, review-delta, review-pr
|
|
30
|
-
CLI: code-review-graph [install|init|build|update|status|watch|visualize|serve|wiki|detect-changes|register|unregister|repos|eval]
|
|
30
|
+
CLI: code-review-graph [install|init|build|update|status|watch|visualize|serve|wiki|detect-changes|postprocess|register|unregister|repos|eval]
|
|
31
|
+
Token efficiency: All tools support detail_level="minimal" for compact output. Always call get_minimal_context_tool first.
|
|
31
32
|
</section>
|
|
32
33
|
|
|
33
34
|
<section name="legal">
|
|
@@ -48,7 +49,7 @@ Configure via CRG_EMBEDDING_MODEL env var or model parameter.
|
|
|
48
49
|
</section>
|
|
49
50
|
|
|
50
51
|
<section name="languages">
|
|
51
|
-
Supported (
|
|
52
|
+
Supported (19): Python, TypeScript/TSX, JavaScript, Vue, Go, Rust, Java, Scala, C#, Ruby, Kotlin, Swift, PHP, Solidity, C/C++, Dart, R, Perl, Lua
|
|
52
53
|
Parser: Tree-sitter via tree-sitter-language-pack
|
|
53
54
|
</section>
|
|
54
55
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code-review-graph"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.2"
|
|
8
8
|
description = "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code"
|
|
9
9
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
10
10
|
license = "MIT"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "code-review-graph",
|
|
3
|
-
"owner": {
|
|
4
|
-
"name": "Tirth Kanani",
|
|
5
|
-
"email": "tirthkanani18@gmail.com"
|
|
6
|
-
},
|
|
7
|
-
"metadata": {
|
|
8
|
-
"description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
|
|
9
|
-
"version": "2.1.0"
|
|
10
|
-
},
|
|
11
|
-
"plugins": [
|
|
12
|
-
{
|
|
13
|
-
"name": "code-review-graph",
|
|
14
|
-
"source": "./",
|
|
15
|
-
"description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
|
|
16
|
-
"version": "2.1.0",
|
|
17
|
-
"category": "development",
|
|
18
|
-
"keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"]
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "code-review-graph",
|
|
3
|
-
"description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
|
|
4
|
-
"version": "2.1.0",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Tirth Kanani",
|
|
7
|
-
"email": "tirthkanani18@gmail.com",
|
|
8
|
-
"url": "https://github.com/tirth8205"
|
|
9
|
-
},
|
|
10
|
-
"homepage": "https://code-review-graph.com",
|
|
11
|
-
"repository": "https://github.com/tirth8205/code-review-graph",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"],
|
|
14
|
-
"mcpServers": {
|
|
15
|
-
"code-review-graph": {
|
|
16
|
-
"command": "uvx",
|
|
17
|
-
"args": ["code-review-graph", "serve"]
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"skills": "./skills/"
|
|
21
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/express.yaml
RENAMED
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/fastapi.yaml
RENAMED
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/flask.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/httpx.yaml
RENAMED
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/nextjs.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/token_benchmark.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -21,8 +21,6 @@ from .tools import (
|
|
|
21
21
|
apply_refactor_func,
|
|
22
22
|
build_or_update_graph,
|
|
23
23
|
cross_repo_search_func,
|
|
24
|
-
get_minimal_context,
|
|
25
|
-
run_postprocess,
|
|
26
24
|
detect_changes_func,
|
|
27
25
|
embed_graph,
|
|
28
26
|
find_large_functions,
|
|
@@ -33,6 +31,7 @@ from .tools import (
|
|
|
33
31
|
get_docs_section,
|
|
34
32
|
get_flow,
|
|
35
33
|
get_impact_radius,
|
|
34
|
+
get_minimal_context,
|
|
36
35
|
get_review_context,
|
|
37
36
|
get_wiki_page_func,
|
|
38
37
|
list_communities_func,
|
|
@@ -41,6 +40,7 @@ from .tools import (
|
|
|
41
40
|
list_repos_func,
|
|
42
41
|
query_graph,
|
|
43
42
|
refactor_func,
|
|
43
|
+
run_postprocess,
|
|
44
44
|
semantic_search_nodes,
|
|
45
45
|
)
|
|
46
46
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -46,9 +46,6 @@ from ._common import (
|
|
|
46
46
|
# -- build ------------------------------------------------------------------
|
|
47
47
|
from .build import build_or_update_graph, run_postprocess
|
|
48
48
|
|
|
49
|
-
# -- context ----------------------------------------------------------------
|
|
50
|
-
from .context import get_minimal_context
|
|
51
|
-
|
|
52
49
|
# -- community_tools --------------------------------------------------------
|
|
53
50
|
from .community_tools import (
|
|
54
51
|
get_architecture_overview_func,
|
|
@@ -56,6 +53,9 @@ from .community_tools import (
|
|
|
56
53
|
list_communities_func,
|
|
57
54
|
)
|
|
58
55
|
|
|
56
|
+
# -- context ----------------------------------------------------------------
|
|
57
|
+
from .context import get_minimal_context
|
|
58
|
+
|
|
59
59
|
# -- docs -------------------------------------------------------------------
|
|
60
60
|
from .docs import embed_graph, generate_wiki_func, get_docs_section, get_wiki_page_func
|
|
61
61
|
|
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/community_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/refactor_tools.py
RENAMED
|
File without changes
|
{code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/registry_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|